#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)
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
{.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)
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 *
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
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;
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 */
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;
}
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;
}
/* 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
*/
#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);
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
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 */