]> Zhao Yanbai Git Server - minix.git/commitdiff
arm:determine board_id using bootargs.board_name 91/1191/2
authorKees Jongenburger <kees.jongenburger@gmail.com>
Fri, 13 Dec 2013 13:00:06 +0000 (14:00 +0100)
committerKees Jongenburger <kees.jongenburger@gmail.com>
Tue, 17 Dec 2013 10:32:38 +0000 (11:32 +0100)
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
kernel/arch/earm/pre_init.c
kernel/arch/i386/pre_init.c
kernel/main.c

index 143859e1ee44b9a6fd9a76f5df85556be53e2c53..1a6bfb55ea6891e9941b72df1d5491f430cde21b 100644 (file)
@@ -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
index 9778eed1b81b6f7c016b2871f130464fce2cc7b6..77b6c68f4d51621947972805f9138ad0c69fc65f 100644 (file)
@@ -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 */
index d6ad07f97261cf6c93a745fffc38d6e0aa038892..6a53ec9c8b0022f160a1218c252e397f66458302 100644 (file)
@@ -7,6 +7,7 @@
 #include <minix/minlib.h>
 #include <minix/const.h>
 #include <minix/type.h>
+#include <minix/board.h>
 #include <minix/com.h>
 #include <sys/types.h>
 #include <sys/param.h>
@@ -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
index 9978b5b513c1ae760fc3c51e2ae49b4807f4175f..66ab7a0cd0588b5e4ea3ab8f94c8987c57fd0a4e 100644 (file)
@@ -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();