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
This commit is contained in:
parent
8c02dd7b2a
commit
3a2fb1ae8c
@ -19,9 +19,9 @@
|
|||||||
#define MINIX_BOARD_SHIFT (8)
|
#define MINIX_BOARD_SHIFT (8)
|
||||||
#define MINIX_BOARD_VARIANT_SHIFT (0)
|
#define MINIX_BOARD_VARIANT_SHIFT (0)
|
||||||
|
|
||||||
/* 8 bits */
|
/* 4 bits */
|
||||||
#define MINIX_BOARD_ARCH_MASK \
|
#define MINIX_BOARD_ARCH_MASK \
|
||||||
(0XFF << MINIX_BOARD_ARCH_SHIFT)
|
(0XF << MINIX_BOARD_ARCH_SHIFT)
|
||||||
/* 4 bits */
|
/* 4 bits */
|
||||||
#define MINIX_BOARD_ARCH_VARIANT_MASK \
|
#define MINIX_BOARD_ARCH_VARIANT_MASK \
|
||||||
(0XF << MINIX_BOARD_ARCH_VARIANT_SHIFT)
|
(0XF << MINIX_BOARD_ARCH_VARIANT_SHIFT)
|
||||||
@ -142,11 +142,12 @@ struct shortname2id
|
|||||||
unsigned int id;
|
unsigned int id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* mapping from fields given by the bootloader to board id's */
|
/* mapping from fields given by the bootloader to board id's */
|
||||||
static struct shortname2id shortname2id[] = {
|
static struct shortname2id shortname2id[] = {
|
||||||
{.name = "BBXM",.id = BOARD_ID_BBXM},
|
{.name = "BBXM",.id = BOARD_ID_BBXM},
|
||||||
{.name = "A335BONE",.id = BOARD_ID_BBW},
|
{.name = "A335BONE",.id = BOARD_ID_BBW},
|
||||||
{.name = "BBB",.id = BOARD_ID_BBB},
|
{.name = "A335BNLT",.id = BOARD_ID_BBB},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct board_id2name
|
struct board_id2name
|
||||||
@ -163,6 +164,17 @@ static struct board_id2name board_id2name[] = {
|
|||||||
{.id = BOARD_ID_BBB,.name = "ARM-ARMV7-TI-BB-BLACK"},
|
{.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 */
|
/* returns 0 if no board was found that match that id */
|
||||||
static int
|
static int
|
||||||
get_board_id_by_short_name(const char *name)
|
get_board_id_by_short_name(const char *name)
|
||||||
@ -176,6 +188,19 @@ get_board_id_by_short_name(const char *name)
|
|||||||
return 0;
|
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
|
/* convert a board id to a board name to use later
|
||||||
returns NULL if no board was found that match that id */
|
returns NULL if no board was found that match that id */
|
||||||
static const char *
|
static const char *
|
||||||
@ -190,4 +215,18 @@ get_board_name(unsigned int id)
|
|||||||
return NULL;
|
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
|
#endif
|
||||||
|
@ -41,8 +41,73 @@ int kernel_may_alloc = 1;
|
|||||||
extern u32_t _edata;
|
extern u32_t _edata;
|
||||||
extern u32_t _end;
|
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 *p = bigbuf;
|
||||||
char *bufend = bigbuf + MULTIBOOT_PARAM_BUF_SIZE;
|
char *bufend = bigbuf + MULTIBOOT_PARAM_BUF_SIZE;
|
||||||
char *q;
|
char *q;
|
||||||
@ -57,18 +122,24 @@ static int mb_set_param(char *bigbuf, char *name, char *value, kinfo_t *cbi)
|
|||||||
while (*p) {
|
while (*p) {
|
||||||
if (strncmp(p, name, namelen) == 0 && p[namelen] == '=') {
|
if (strncmp(p, name, namelen) == 0 && p[namelen] == '=') {
|
||||||
q = p;
|
q = p;
|
||||||
while (*q) q++;
|
/* let q point to the end of the entry */
|
||||||
for (q++; q < bufend; q++, p++)
|
while (*q) q++;
|
||||||
|
/* now copy the remained of the buffer */
|
||||||
|
for (q++; q < bufend; q++, p++)
|
||||||
*p = *q;
|
*p = *q;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
while (*p++)
|
|
||||||
;
|
/* find the end of the buffer */
|
||||||
|
while (*p++);
|
||||||
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++;
|
if (p > bigbuf) p++;
|
||||||
|
|
||||||
/* Make sure there's enough space for the new parameter */
|
/* 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] = '=';
|
p[namelen] = '=';
|
||||||
strcpy(p + namelen + 1, value);
|
strcpy(p + namelen + 1, value);
|
||||||
p[namelen + valuelen + 1] = 0;
|
p[namelen + valuelen + 1] = 0;
|
||||||
p[namelen + valuelen + 2] = 0;
|
p[namelen + valuelen + 2] = 0; /* end with a second delimiter */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,8 +249,8 @@ void get_parameters(kinfo_t *cbi, char *bootargs)
|
|||||||
while (*p) {
|
while (*p) {
|
||||||
var_i = 0;
|
var_i = 0;
|
||||||
value_i = 0;
|
value_i = 0;
|
||||||
while (*p == ' ') p++;
|
while (*p == ' ') p++; /* skip spaces */
|
||||||
if (!*p) break;
|
if (!*p) break; /* is this the end? */
|
||||||
while (*p && *p != '=' && *p != ' ' && var_i < BUF - 1)
|
while (*p && *p != '=' && *p != ' ' && var_i < BUF - 1)
|
||||||
var[var_i++] = *p++ ;
|
var[var_i++] = *p++ ;
|
||||||
var[var_i] = 0;
|
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 */
|
/* let higher levels know what we are booting on */
|
||||||
mb_set_param(cbi->param_buf, ARCHVARNAME, "earm", cbi);
|
mb_set_param(cbi->param_buf, ARCHVARNAME, (char *)get_board_arch_name(machine.board_id), cbi);
|
||||||
#ifdef AM335X
|
mb_set_param(cbi->param_buf, BOARDVARNAME,(char *)get_board_name(machine.board_id) , cbi);
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
/* round user stack down to leave a gap to catch kernel
|
/* round user stack down to leave a gap to catch kernel
|
||||||
* stack overflow; and to distinguish kernel and user addresses
|
* 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")
|
#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 */
|
/* Clear BSS */
|
||||||
memset(&_edata, 0, (u32_t)&_end - (u32_t)&_edata);
|
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){
|
if (argc != 2){
|
||||||
POORMANS_FAILURE_NOTIFICATION;
|
POORMANS_FAILURE_NOTIFICATION;
|
||||||
}
|
}
|
||||||
|
bootargs = argv[1];
|
||||||
|
set_machine_id(bootargs);
|
||||||
omap3_ser_init();
|
omap3_ser_init();
|
||||||
/* Get our own copy boot params pointed to by ebx.
|
/* Get our own copy boot params pointed to by ebx.
|
||||||
* Here we find out whether we should do serial output.
|
* 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
|
/* Make and load a pagetable that will map the kernel
|
||||||
* to where it should be; but first a 1:1 mapping so
|
* 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 raise(int n) { panic("raise(%d)\n", n); }
|
||||||
int kern_phys_map_ptr( phys_bytes base_address, vir_bytes io_size,
|
int kern_phys_map_ptr( phys_bytes base_address, vir_bytes io_size,
|
||||||
struct kern_phys_map * priv, vir_bytes ptr) {};
|
struct kern_phys_map * priv, vir_bytes ptr) {};
|
||||||
|
struct machine machine; /* pre init stage machine */
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <minix/minlib.h>
|
#include <minix/minlib.h>
|
||||||
#include <minix/const.h>
|
#include <minix/const.h>
|
||||||
#include <minix/type.h>
|
#include <minix/type.h>
|
||||||
|
#include <minix/board.h>
|
||||||
#include <minix/com.h>
|
#include <minix/com.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/param.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 */
|
/* let higher levels know what we are booting on */
|
||||||
mb_set_param(cbi->param_buf, ARCHVARNAME, "i386", cbi);
|
mb_set_param(cbi->param_buf, ARCHVARNAME, (char *)get_board_arch_name(BOARD_ID_INTEL), cbi);
|
||||||
mb_set_param(cbi->param_buf, BOARDVARNAME, "i586", 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
|
/* round user stack down to leave a gap to catch kernel
|
||||||
* stack overflow; and to distinguish kernel and user addresses
|
* stack overflow; and to distinguish kernel and user addresses
|
||||||
|
@ -131,14 +131,9 @@ void kmain(kinfo_t *local_cbi)
|
|||||||
memcpy(&kinfo, local_cbi, sizeof(kinfo));
|
memcpy(&kinfo, local_cbi, sizeof(kinfo));
|
||||||
memcpy(&kmess, kinfo.kmess, sizeof(kmess));
|
memcpy(&kmess, kinfo.kmess, sizeof(kmess));
|
||||||
|
|
||||||
/* The following will be replaced with code getting this information from the
|
/* We have done this exercise in pre_init so we expect this code
|
||||||
bootloader */
|
to simply work! */
|
||||||
#ifdef DM37XX
|
machine.board_id = get_board_id_by_name(env_get(BOARDVARNAME));
|
||||||
machine.board_id = BOARD_ID_BBXM;
|
|
||||||
#endif
|
|
||||||
#ifdef AM335X
|
|
||||||
machine.board_id = BOARD_ID_BBW;
|
|
||||||
#endif
|
|
||||||
#ifdef __arm__
|
#ifdef __arm__
|
||||||
/* We want to initialize serial before we do any output */
|
/* We want to initialize serial before we do any output */
|
||||||
omap3_ser_init();
|
omap3_ser_init();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user