Kernel: Generic boot device parsing method
authorWill Sowerbutts <will@sowerbutts.com>
Sat, 14 Feb 2015 14:22:43 +0000 (14:22 +0000)
committerWill Sowerbutts <will@sowerbutts.com>
Sat, 14 Feb 2015 14:53:05 +0000 (14:53 +0000)
Kernel/include/kernel.h
Kernel/platform-n8vem-mark4/config.h
Kernel/platform-n8vem-mark4/discard.c
Kernel/platform-p112/config.h
Kernel/platform-p112/discard.c
Kernel/start.c

index d83faff..1dd482f 100644 (file)
@@ -580,12 +580,6 @@ struct selmap {
 extern void trap_monitor(void);
 extern void idump(void);
 
-/* start.c */
-#ifndef CONFIG_BOOTDEVICE
-#define default_bootdevice     bootdevice
-#endif
-extern uint16_t default_bootdevice(unsigned char *s);
-
 /* platform/device.c */
 extern bool validdev(uint16_t dev);
 
index ac11091..d61c151 100644 (file)
@@ -14,8 +14,6 @@
 #define CONFIG_BANK_FIXED
 /* Permit large I/O requests to bypass cache and go direct to userspace */
 #define CONFIG_LARGE_IO_DIRECT
-/* Platform defined bootdevice() */
-#define CONFIG_BOOTDEVICE
 /* 8 60K banks, 1 is kernel */
 #define MAX_MAPS       8
 #define MAP_SIZE       0xF000U
@@ -38,6 +36,7 @@
 
 /* We need a tidier way to do this from the loader */
 #define CMDLINE        (0x0081)  /* Location of root dev name */
+#define BOOTDEVICENAMES "hd#"
 
 //#define SWAPDEV  (256 + 1)  /* Device for swapping. (z80pack drive J) */
 #define NBUFS    10       /* Number of block buffers */
index 0fa6f6b..5cdf680 100644 (file)
@@ -24,53 +24,3 @@ void map_init(void)
     copy_and_map_process(&init_process->p_page);
     /* kernel bank udata (0x300 bytes) is never used again -- could be reused? */
 }
-
-uint16_t bootdevice(unsigned char *s)
-{
-    unsigned int b = 0, n = 0;
-    unsigned char c;
-    bool ok = false;
-
-    /* skip spaces */
-    while(*s == ' ')
-        s++;
-
-    /* we're expecting one of;
-     * hdX<num>
-     * fd<num>
-     * <num>
-     */
-
-
-    switch(*s | 32){
-        case 'f': /* fd */
-            b += 256;
-        case 'h': /* hd */
-            s++;
-            ok = true;
-            if((*s | 32) != 'd')
-                return -1;
-            s++;
-            if(b == 0){ /* hdX */
-                c = (*s | 32) - 'a';
-                if(c & 0xF0)
-                    return -1;
-                b += c << 4;
-                s++;
-            }
-            break;
-        default:
-            break;
-    }
-
-    while(*s >= '0' && *s <= '9'){
-        n = (n*10) + (*s - '0');
-        s++;
-        ok = true;
-    }
-
-    if(ok)
-        return (b + n);
-    else
-        return -1;
-}
index a3a810b..6480c38 100644 (file)
@@ -14,8 +14,6 @@
 #define CONFIG_BANK_FIXED
 /* Permit large I/O requests to bypass cache and go direct to userspace */
 #define CONFIG_LARGE_IO_DIRECT
-/* Platform defined bootdevice() */
-#define CONFIG_BOOTDEVICE
 /* 8 60K banks, 1 is kernel */
 #define MAX_MAPS       16
 #define MAP_SIZE       0xF000U
@@ -41,6 +39,7 @@
 
 /* We need a tidier way to do this from the loader */
 #define CMDLINE        (0x0081)  /* Location of root dev name */
+#define BOOTDEVICENAMES "hd#,fd"
 
 /* Device parameters */
 #define NUM_DEV_TTY 4
index 9ee76cc..e8eb7f1 100644 (file)
@@ -28,53 +28,3 @@ void map_init(void)
     copy_and_map_process(&init_process->p_page);
     /* kernel bank udata (0x300 bytes) is never used again -- could be reused? */
 }
-
-uint16_t bootdevice(unsigned char *s)
-{
-    unsigned int b = 0, n = 0;
-    unsigned char c;
-    bool ok = false;
-
-    /* skip spaces */
-    while(*s == ' ')
-        s++;
-
-    /* we're expecting one of;
-     * hdX<num>
-     * fd<num>
-     * <num>
-     */
-
-
-    switch(*s | 32){
-        case 'f': /* fd */
-            b += 256;
-        case 'h': /* hd */
-            s++;
-            ok = true;
-            if((*s | 32) != 'd')
-                return -1;
-            s++;
-            if(b == 0){ /* hdX */
-                c = (*s | 32) - 'a';
-                if(c & 0xF0)
-                    return -1;
-                b += c << 4;
-                s++;
-            }
-            break;
-        default:
-            break;
-    }
-
-    while(*s >= '0' && *s <= '9'){
-        n = (n*10) + (*s - '0');
-        s++;
-        ok = true;
-    }
-
-    if(ok)
-        return (b + n);
-    else
-        return -1;
-}
index 26a45d2..1fdacc7 100644 (file)
@@ -83,25 +83,118 @@ void create_init(void)
        udata.u_argn2 = (arg_t)(PROGLOAD + 0xb); /* Environment (none) */
 }
 
-/* to sensibly parse device names this needs to be platform-specific,
-   this default version parses minor numbers only */
-uint16_t default_bootdevice(unsigned char *s)
+/* Parse boot device name, based on platform defined BOOTDEVICENAMES string.
+ *
+ * This string is a list of device driver names delimited by commas. Device
+ * driver names should be listed in the same order as entries in dev_tab.
+ * Unbootable slots should be listed with an empty name. The position in the
+ * list of names specifies the top 8 bits of the minor number.
+ *
+ * Names which end in a # character expect a letter suffix which specifies bits
+ * 4--7 of the minor number.
+ *
+ * All names can be followed by an index number which is added to the minor
+ * number. The user can provide only this index number, in which case it
+ * specifies the full minor number.
+ *
+ * Some example BOOTDEVICENAMES:
+ * "hd#,fd"
+ *    hda   gives 0x0000
+ *    hda1  gives 0x0001
+ *    hdc   gives 0x0020
+ *    hdc3  gives 0x0023
+ *    fd0   gives 0x0100
+ *    fd15  gives 0x010F
+ *    17    gives 0x0011
+ *
+ * "fd,hd#,,ram"  (slot 2 in dev_tab is the tty device which is unbootable)
+ *    fd0   gives 0x0000
+ *    fd1   gives 0x0001
+ *    hda1  gives 0x0101
+ *    hdc3  gives 0x0123
+ *    ram7  gives 0x0307
+ *    17    gives 0x0011
+ */
+
+#ifndef BOOTDEVICENAMES
+#define BOOTDEVICENAMES "" /* numeric parsing only */
+#endif
+
+uint16_t bootdevice(const char *devname)
 {
-    unsigned int r = 0;
-
-    /* skip spaces */
-    while(*s == ' ')
-        s++;
-
-    while(true){
-        if(*s >= '0' && *s <= '9'){
-            r = (r*10) + (*s - '0');
-        }else if(*s == '\r' || *s == '\n' || *s == 0){
-            return r;
-        }else
-            return BAD_ROOT_DEV;
-        s++;
-    }
+       bool match = true;
+       unsigned int b = 0, n = 0;
+       const char *p, *bdn = BOOTDEVICENAMES;
+       char c, pc;
+
+       /* skip spaces at start of string */
+       while(*devname == ' '){
+               devname++;
+       }
+
+       p = devname;
+
+       /* first we try to the match device name */
+       while(true){
+               pc = *p;
+               if(pc >= 'A' && pc <= 'Z')
+                       pc |= 0x20; /* lower case */
+               c = *bdn;
+
+               if(!c){
+                       /* end of device names string */
+                       break;
+               }else if(c == ','){
+                       /* next device driver */
+                       if(match == true && p != devname)
+                               break;
+                       p = devname;
+                       b += 0x100;
+                       match = true;
+                       bdn++;
+                       continue;
+               }else if(match && c == '#'){
+                       /* parse device drive letter */
+                       if(pc < 'a' || pc > 'p')
+                               return BAD_ROOT_DEV;
+                       b += ((pc-'a') << 4);
+                       p++;
+                       break;
+               }else if(match && pc != c){
+                       match = false;
+               }
+               p++;
+               bdn++;
+       }
+
+       /* if we didn't match a device name, start over */
+       if(!match){
+               b = 0;
+               p = devname;
+       }
+
+       /* then we read an index number */
+       while(*p >= '0' && *p <= '9'){
+               n = (n*10) + (*p - '0');
+               p++;
+               match = true;
+       }
+
+       /* string ends in junk? */
+       switch(*p) {
+               case 0:
+               case '\n':
+               case '\r':
+               case ' ':
+                       break;
+               default:
+                       return BAD_ROOT_DEV;
+       }
+
+       if(match)
+               return (b + n);
+       else
+               return BAD_ROOT_DEV;
 }
 
 uint16_t get_root_dev(void)
@@ -117,7 +210,7 @@ uint16_t get_root_dev(void)
                udata.u_base = (uint8_t*)&bootline;
                udata.u_sysio = 1;
                udata.u_count = sizeof(bootline)-1;
-               udata.u_euid = 0;       /* Always begin as superuser */
+               udata.u_euid = 0;               /* Always begin as superuser */
 
                cdread(TTYDEV, O_RDONLY);       /* read root filesystem name from tty */
                rd = bootdevice(bootline);