From 33c388e1cfba42aa42c1bc543f59a7107c5abd54 Mon Sep 17 00:00:00 2001 From: Will Sowerbutts Date: Sat, 14 Feb 2015 14:22:43 +0000 Subject: [PATCH] Kernel: Generic boot device parsing method --- Kernel/include/kernel.h | 6 -- Kernel/platform-n8vem-mark4/config.h | 3 +- Kernel/platform-n8vem-mark4/discard.c | 50 ---------- Kernel/platform-p112/config.h | 3 +- Kernel/platform-p112/discard.c | 50 ---------- Kernel/start.c | 131 ++++++++++++++++++++++---- 6 files changed, 114 insertions(+), 129 deletions(-) diff --git a/Kernel/include/kernel.h b/Kernel/include/kernel.h index d83faff2..1dd482f6 100644 --- a/Kernel/include/kernel.h +++ b/Kernel/include/kernel.h @@ -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); diff --git a/Kernel/platform-n8vem-mark4/config.h b/Kernel/platform-n8vem-mark4/config.h index ac110917..d61c1511 100644 --- a/Kernel/platform-n8vem-mark4/config.h +++ b/Kernel/platform-n8vem-mark4/config.h @@ -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 */ diff --git a/Kernel/platform-n8vem-mark4/discard.c b/Kernel/platform-n8vem-mark4/discard.c index 0fa6f6b1..5cdf6804 100644 --- a/Kernel/platform-n8vem-mark4/discard.c +++ b/Kernel/platform-n8vem-mark4/discard.c @@ -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 - * fd - * - */ - - - 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; -} diff --git a/Kernel/platform-p112/config.h b/Kernel/platform-p112/config.h index a3a810b9..6480c383 100644 --- a/Kernel/platform-p112/config.h +++ b/Kernel/platform-p112/config.h @@ -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 diff --git a/Kernel/platform-p112/discard.c b/Kernel/platform-p112/discard.c index 9ee76cc9..e8eb7f16 100644 --- a/Kernel/platform-p112/discard.c +++ b/Kernel/platform-p112/discard.c @@ -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 - * fd - * - */ - - - 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; -} diff --git a/Kernel/start.c b/Kernel/start.c index 26a45d2c..1fdacc70 100644 --- a/Kernel/start.c +++ b/Kernel/start.c @@ -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); -- 2.34.1