From 3a2fb1ae8ca0e3a1d317b796e59c378e34e67765 Mon Sep 17 00:00:00 2001 From: Kees Jongenburger Date: Fri, 13 Dec 2013 14:00:06 +0100 Subject: [PATCH] arm:determine board_id using bootargs.board_name On startup determine the board_id based on the board name passed from u-boot. This code also export "board" for use by userland using sysenv. Change-Id: I1064a49497c82b06f50d98650132bc0a7f543568 --- include/minix/board.h | 45 +++++++++++- kernel/arch/earm/pre_init.c | 142 +++++++++++++++++++++++++++++------- kernel/arch/i386/pre_init.c | 5 +- kernel/main.c | 11 +-- 4 files changed, 162 insertions(+), 41 deletions(-) diff --git a/include/minix/board.h b/include/minix/board.h index 143859e1e..1a6bfb55e 100644 --- a/include/minix/board.h +++ b/include/minix/board.h @@ -19,9 +19,9 @@ #define MINIX_BOARD_SHIFT (8) #define MINIX_BOARD_VARIANT_SHIFT (0) -/* 8 bits */ +/* 4 bits */ #define MINIX_BOARD_ARCH_MASK \ - (0XFF << MINIX_BOARD_ARCH_SHIFT) + (0XF << MINIX_BOARD_ARCH_SHIFT) /* 4 bits */ #define MINIX_BOARD_ARCH_VARIANT_MASK \ (0XF << MINIX_BOARD_ARCH_VARIANT_SHIFT) @@ -142,11 +142,12 @@ struct shortname2id unsigned int id; }; + /* mapping from fields given by the bootloader to board id's */ static struct shortname2id shortname2id[] = { {.name = "BBXM",.id = BOARD_ID_BBXM}, {.name = "A335BONE",.id = BOARD_ID_BBW}, - {.name = "BBB",.id = BOARD_ID_BBB}, + {.name = "A335BNLT",.id = BOARD_ID_BBB}, }; struct board_id2name @@ -163,6 +164,17 @@ static struct board_id2name board_id2name[] = { {.id = BOARD_ID_BBB,.name = "ARM-ARMV7-TI-BB-BLACK"}, }; +struct board_arch2arch +{ + unsigned int board_arch; + const char arch[40]; +}; +/* Mapping from board_arch to arch */ +static struct board_arch2arch board_arch2arch[] = { + {.board_arch = MINIX_BOARD_ARCH_ARM ,.arch = "earm"}, + {.board_arch = MINIX_BOARD_ARCH_X86 ,.arch = "i386"}, +}; + /* returns 0 if no board was found that match that id */ static int get_board_id_by_short_name(const char *name) @@ -176,6 +188,19 @@ get_board_id_by_short_name(const char *name) return 0; } +/* returns 0 if no board was found that match that id */ +static int +get_board_id_by_name(const char *name) +{ + int x; + for (x = 0; x < sizeof(board_id2name) / sizeof(board_id2name[0]); x++) { + if (strncmp(name, board_id2name[x].name, 40) == 0) { + return board_id2name[x].id; + } + } + return 0; +} + /* convert a board id to a board name to use later returns NULL if no board was found that match that id */ static const char * @@ -190,4 +215,18 @@ get_board_name(unsigned int id) return NULL; } +/* convert a board id to a board name to use later + returns NULL if no board was found that match that id */ +static const char * +get_board_arch_name(unsigned int id) +{ + int x; + for (x = 0; x < sizeof(board_arch2arch) / sizeof(board_arch2arch[0]); x++) { + if (board_arch2arch[x].board_arch == (id & MINIX_BOARD_ARCH_MASK) ) { + return board_arch2arch[x].arch; + } + } + return NULL; +} + #endif diff --git a/kernel/arch/earm/pre_init.c b/kernel/arch/earm/pre_init.c index 9778eed1b..77b6c68f4 100644 --- a/kernel/arch/earm/pre_init.c +++ b/kernel/arch/earm/pre_init.c @@ -41,8 +41,73 @@ int kernel_may_alloc = 1; extern u32_t _edata; extern u32_t _end; -static int mb_set_param(char *bigbuf, char *name, char *value, kinfo_t *cbi) +/** + * + * The following function combines a few things together + * that can well be done using standard libc like strlen/strstr + * and such but these are not available in pre_init stage. + * + * The function expects content to be in the form of space separated + * key value pairs. + * param content the contents to search in + * param key the key to find (this *should* include the key/value delimiter) + * param value a pointer to an initialized char * of at least value_max_len length + * param value_max_len the maximum length of the value to store in value including + * the end char + * +**/ +int find_value(char * content,char * key,char *value,int value_max_len){ + + char *iter,*keyp; + int key_len,content_len,match_len,value_len; + + /* return if the input is invalid */ + if (key == NULL || content == NULL || value == NULL){ + return 1; + } + + /* find the key and content length */ + key_len = content_len =0; + for(iter = key ; *iter != '\0'; iter++, key_len++); + for(iter = content ; *iter != '\0'; iter++, content_len++); + + /* return if key or content length invalid */ + if (key_len == 0 || content_len == 0) { + return 1; + } + + /* now find the key in the contents */ + match_len =0; + for (iter = content ,keyp=key; match_len < key_len && *iter != '\0' ; iter++){ + if (*iter == *keyp){ + match_len++; + keyp++; + continue; + } + /* The current key does not match the value , reset */ + match_len =0; + keyp=key; + } + + if (match_len == key_len){ + printf("key found at %d %s\n", match_len, &content[match_len]); + value_len = 0; + /* copy the content to the value char iter already points to the first + char value */ + while(*iter != '\0' && *iter != ' ' && value_len + 1< value_max_len){ + *value++ = *iter++; + value_len++; + } + *value='\0'; + return 0; + } + return 1; /* not found */ +} + +static int mb_set_param(char *bigbuf,char *name,char *value, kinfo_t *cbi) { + /* bigbuf contains a list of key=value pairs separated by \0 char. + * The list itself is ended by a second \0 terminator*/ char *p = bigbuf; char *bufend = bigbuf + MULTIBOOT_PARAM_BUF_SIZE; char *q; @@ -57,18 +122,24 @@ static int mb_set_param(char *bigbuf, char *name, char *value, kinfo_t *cbi) while (*p) { if (strncmp(p, name, namelen) == 0 && p[namelen] == '=') { q = p; - while (*q) q++; - for (q++; q < bufend; q++, p++) + /* let q point to the end of the entry */ + while (*q) q++; + /* now copy the remained of the buffer */ + for (q++; q < bufend; q++, p++) *p = *q; break; } - while (*p++) - ; + + /* find the end of the buffer */ + while (*p++); p++; } - for (p = bigbuf; p < bufend && (*p || *(p + 1)); p++) - ; + + /* find the first empty spot */ + for (p = bigbuf; p < bufend && (*p || *(p + 1)); p++); + + /* unless we are the first entry step over the delimiter */ if (p > bigbuf) p++; /* Make sure there's enough space for the new parameter */ @@ -79,7 +150,7 @@ static int mb_set_param(char *bigbuf, char *name, char *value, kinfo_t *cbi) p[namelen] = '='; strcpy(p + namelen + 1, value); p[namelen + valuelen + 1] = 0; - p[namelen + valuelen + 2] = 0; + p[namelen + valuelen + 2] = 0; /* end with a second delimiter */ return 0; } @@ -178,8 +249,8 @@ void get_parameters(kinfo_t *cbi, char *bootargs) while (*p) { var_i = 0; value_i = 0; - while (*p == ' ') p++; - if (!*p) break; + while (*p == ' ') p++; /* skip spaces */ + if (!*p) break; /* is this the end? */ while (*p && *p != '=' && *p != ' ' && var_i < BUF - 1) var[var_i++] = *p++ ; var[var_i] = 0; @@ -193,22 +264,9 @@ void get_parameters(kinfo_t *cbi, char *bootargs) } /* let higher levels know what we are booting on */ - mb_set_param(cbi->param_buf, ARCHVARNAME, "earm", cbi); -#ifdef AM335X - int id = get_board_id_by_short_name("A335BONE"); - printf("BOARD ID=0x%08x\n",id); - const char * boardname = get_board_name(id); - printf("BOARD NAME=%s\n",boardname); - mb_set_param(cbi->param_buf, BOARDVARNAME,(char *) boardname, cbi); -#endif -#ifdef DM337x - int id = get_board_id_by_short_name("BBXM"); - printf("BOARD ID=0x%08x\n",id); - const char * boardname = get_board_name(id); - printf("BOARD NAME=%s\n",boardname); - mb_set_param(cbi->param_buf, BOARDVARNAME,(char *) boardname, cbi); -#endif - + mb_set_param(cbi->param_buf, ARCHVARNAME, (char *)get_board_arch_name(machine.board_id), cbi); + mb_set_param(cbi->param_buf, BOARDVARNAME,(char *)get_board_name(machine.board_id) , cbi); + /* round user stack down to leave a gap to catch kernel * stack overflow; and to distinguish kernel and user addresses @@ -285,8 +343,33 @@ void get_parameters(kinfo_t *cbi, char *bootargs) */ #define POORMANS_FAILURE_NOTIFICATION asm volatile("svc #00\n") -kinfo_t *pre_init(u32_t argc, char **argv) +/* use the passed cmdline argument to determine the machine id */ +void set_machine_id(char *cmdline) +{ + + char boardname[20]; + memset(boardname,'\0',20); + if (find_value(cmdline,"board_name=",boardname,20)){ + /* we expect the bootloader to pass a board_name as argument + * this however did not happen and given we still are in early + * boot we can't use the serial. We therefore generate an interrupt + * and hope the bootloader will do something nice with it */ + POORMANS_FAILURE_NOTIFICATION; + } + machine.board_id = get_board_id_by_short_name(boardname); + + if (machine.board_id ==0){ + /* same thing as above there is no safe escape */ + POORMANS_FAILURE_NOTIFICATION; + } +} + +kinfo_t *pre_init(int argc, char **argv) { + char *bootargs; + /* This is the main "c" entry point into the kernel. It gets called + from head.S */ + /* Clear BSS */ memset(&_edata, 0, (u32_t)&_end - (u32_t)&_edata); @@ -297,11 +380,13 @@ kinfo_t *pre_init(u32_t argc, char **argv) if (argc != 2){ POORMANS_FAILURE_NOTIFICATION; } + bootargs = argv[1]; + set_machine_id(bootargs); omap3_ser_init(); /* Get our own copy boot params pointed to by ebx. * Here we find out whether we should do serial output. */ - get_parameters(&kinfo, argv[1]); + get_parameters(&kinfo, bootargs); /* Make and load a pagetable that will map the kernel * to where it should be; but first a 1:1 mapping so @@ -329,3 +414,4 @@ void busy_delay_ms(int x) { } int raise(int n) { panic("raise(%d)\n", n); } int kern_phys_map_ptr( phys_bytes base_address, vir_bytes io_size, struct kern_phys_map * priv, vir_bytes ptr) {}; +struct machine machine; /* pre init stage machine */ diff --git a/kernel/arch/i386/pre_init.c b/kernel/arch/i386/pre_init.c index d6ad07f97..6a53ec9c8 100644 --- a/kernel/arch/i386/pre_init.c +++ b/kernel/arch/i386/pre_init.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -153,8 +154,8 @@ void get_parameters(u32_t ebx, kinfo_t *cbi) } /* let higher levels know what we are booting on */ - mb_set_param(cbi->param_buf, ARCHVARNAME, "i386", cbi); - mb_set_param(cbi->param_buf, BOARDVARNAME, "i586", cbi); + mb_set_param(cbi->param_buf, ARCHVARNAME, (char *)get_board_arch_name(BOARD_ID_INTEL), cbi); + mb_set_param(cbi->param_buf, BOARDVARNAME,(char *)get_board_name(BOARD_ID_INTEL) , cbi); /* round user stack down to leave a gap to catch kernel * stack overflow; and to distinguish kernel and user addresses diff --git a/kernel/main.c b/kernel/main.c index 9978b5b51..66ab7a0cd 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -131,14 +131,9 @@ void kmain(kinfo_t *local_cbi) memcpy(&kinfo, local_cbi, sizeof(kinfo)); memcpy(&kmess, kinfo.kmess, sizeof(kmess)); -/* The following will be replaced with code getting this information from the - bootloader */ -#ifdef DM37XX - machine.board_id = BOARD_ID_BBXM; -#endif -#ifdef AM335X - machine.board_id = BOARD_ID_BBW; -#endif + /* We have done this exercise in pre_init so we expect this code + to simply work! */ + machine.board_id = get_board_id_by_name(env_get(BOARDVARNAME)); #ifdef __arm__ /* We want to initialize serial before we do any output */ omap3_ser_init(); -- 2.44.0