Sconfig: parse Kconfig options from devicetree.cb
Mainboard and chip Kconfig files have several build options that are redundant with information in devicetree.cb. This patch enables sconfig to auto-generate equivalent configuration. sconfig -s Generates mainboard's static.c file, as before. sconfig -b This operation creates mainboard's bootblock init code. By default, for every chip listed in mainboard/devicetree.cb, if there is a chip/bootblock.c file, the init function is called. A mainboard/bootblock.c file can be added to override default behaviour. sconfig -k This operation generates select -options for component paths. Change-Id: I808d44af552dbc5e0565d6a0f4f72c7be9f5740e Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-on: http://review.coreboot.org/472 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
This commit is contained in:
parent
f28dbe0c5d
commit
472d9025e5
|
@ -29,6 +29,14 @@ struct header headers;
|
||||||
|
|
||||||
static int devcount = 0;
|
static int devcount = 0;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
STATIC_MODE,
|
||||||
|
BOOTBLOCK_MODE,
|
||||||
|
KCONFIG_MODE
|
||||||
|
} scan_t;
|
||||||
|
|
||||||
|
static scan_t scan_mode = STATIC_MODE;
|
||||||
|
|
||||||
static struct device root;
|
static struct device root;
|
||||||
static struct device mainboard = {
|
static struct device mainboard = {
|
||||||
.name = "mainboard",
|
.name = "mainboard",
|
||||||
|
@ -116,21 +124,28 @@ void postprocess_devtree(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void translate_name(char *str, int uppercase)
|
||||||
|
{
|
||||||
|
char *c;
|
||||||
|
for (c = str; *c; c++) {
|
||||||
|
if (*c == '/') *c = '_';
|
||||||
|
if (*c == '-') *c = '_';
|
||||||
|
if (uppercase)
|
||||||
|
*c = toupper(*c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct device *new_chip(struct device *parent, struct device *bus, char *path) {
|
struct device *new_chip(struct device *parent, struct device *bus, char *path) {
|
||||||
struct device *new_chip = new_dev(parent, bus);
|
struct device *new_chip = new_dev(parent, bus);
|
||||||
new_chip->chiph_exists = 1;
|
new_chip->chiph_exists = 1;
|
||||||
new_chip->name = path;
|
new_chip->name = path;
|
||||||
new_chip->name_underscore = strdup(new_chip->name);
|
new_chip->name_underscore = strdup(new_chip->name);
|
||||||
char *c;
|
translate_name(new_chip->name_underscore, 0);
|
||||||
for (c = new_chip->name_underscore; *c; c++) {
|
|
||||||
if (*c == '/') *c = '_';
|
|
||||||
if (*c == '-') *c = '_';
|
|
||||||
}
|
|
||||||
new_chip->type = chip;
|
new_chip->type = chip;
|
||||||
new_chip->chip = new_chip;
|
new_chip->chip = new_chip;
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char *chip_h = malloc(strlen(path)+12);
|
char *chip_h = malloc(strlen(path)+18);
|
||||||
sprintf(chip_h, "src/%s", path);
|
sprintf(chip_h, "src/%s", path);
|
||||||
if ((stat(chip_h, &st) == -1) && (errno == ENOENT)) {
|
if ((stat(chip_h, &st) == -1) && (errno == ENOENT)) {
|
||||||
fprintf(stderr, "ERROR: Chip component %s does not exist.\n",
|
fprintf(stderr, "ERROR: Chip component %s does not exist.\n",
|
||||||
|
@ -138,9 +153,15 @@ struct device *new_chip(struct device *parent, struct device *bus, char *path) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(chip_h, "src/%s/chip.h", path);
|
if (scan_mode == STATIC_MODE)
|
||||||
if ((stat(chip_h, &st) == -1) && (errno == ENOENT))
|
sprintf(chip_h, "src/%s/chip.h", path);
|
||||||
new_chip->chiph_exists = 0;
|
else if (scan_mode == BOOTBLOCK_MODE)
|
||||||
|
sprintf(chip_h, "src/%s/bootblock.c", path);
|
||||||
|
|
||||||
|
if ((scan_mode == STATIC_MODE) || (scan_mode == BOOTBLOCK_MODE)) {
|
||||||
|
if ((stat(chip_h, &st) == -1) && (errno == ENOENT))
|
||||||
|
new_chip->chiph_exists = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (parent->latestchild) {
|
if (parent->latestchild) {
|
||||||
parent->latestchild->next_sibling = new_chip;
|
parent->latestchild->next_sibling = new_chip;
|
||||||
|
@ -153,7 +174,7 @@ struct device *new_chip(struct device *parent, struct device *bus, char *path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_header(struct device *dev) {
|
void add_header(struct device *dev) {
|
||||||
if (dev->chiph_exists) {
|
if ((dev->chiph_exists) || (scan_mode == KCONFIG_MODE)){
|
||||||
int include_exists = 0;
|
int include_exists = 0;
|
||||||
struct header *h = &headers;
|
struct header *h = &headers;
|
||||||
while (h->next) {
|
while (h->next) {
|
||||||
|
@ -399,7 +420,8 @@ static void pass1(FILE *fil, struct device *ptr) {
|
||||||
}
|
}
|
||||||
if ((ptr->type == chip) && (ptr->chiph_exists)) {
|
if ((ptr->type == chip) && (ptr->chiph_exists)) {
|
||||||
if (ptr->reg) {
|
if (ptr->reg) {
|
||||||
fprintf(fil, "struct %s_config %s_info_%d\t= {\n", ptr->name_underscore, ptr->name_underscore, ptr->id);
|
fprintf(fil, "struct %s_config %s_info_%d\t= {\n",
|
||||||
|
ptr->name_underscore, ptr->name_underscore, ptr->id);
|
||||||
struct reg *r = ptr->reg;
|
struct reg *r = ptr->reg;
|
||||||
while (r) {
|
while (r) {
|
||||||
fprintf(fil, "\t.%s = %s,\n", r->key, r->value);
|
fprintf(fil, "\t.%s = %s,\n", r->key, r->value);
|
||||||
|
@ -407,7 +429,8 @@ static void pass1(FILE *fil, struct device *ptr) {
|
||||||
}
|
}
|
||||||
fprintf(fil, "};\n\n");
|
fprintf(fil, "};\n\n");
|
||||||
} else {
|
} else {
|
||||||
fprintf(fil, "struct %s_config %s_info_%d;\n", ptr->name_underscore, ptr->name_underscore, ptr->id);
|
fprintf(fil, "struct %s_config %s_info_%d;\n",
|
||||||
|
ptr->name_underscore, ptr->name_underscore, ptr->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -441,22 +464,60 @@ static void inherit_subsystem_ids(FILE *file, struct device *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void usage(void)
|
||||||
|
{
|
||||||
|
printf("usage: sconfig vendor/mainboard outputdir [-{s|b|k} outputfile]\n");
|
||||||
|
printf("\t-s file\tcreate ramstage static device map\n");
|
||||||
|
printf("\t-b file\tcreate bootblock init_mainboard()\n");
|
||||||
|
printf("\t-k file\tcreate Kconfig devicetree section\n");
|
||||||
|
printf("Defaults to \"-s static.c\" if no {s|b|k} specified.\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
if (argc != 3) {
|
if (argc < 3)
|
||||||
printf("usage: sconfig vendor/mainboard outputdir\n");
|
usage();
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
char *mainboard=argv[1];
|
char *mainboard=argv[1];
|
||||||
char *outputdir=argv[2];
|
char *outputdir=argv[2];
|
||||||
char *devtree=malloc(strlen(mainboard)+30);
|
char *devtree=malloc(strlen(mainboard)+30);
|
||||||
char *outputc=malloc(strlen(outputdir)+10);
|
|
||||||
sprintf(devtree, "src/mainboard/%s/devicetree.cb", mainboard);
|
sprintf(devtree, "src/mainboard/%s/devicetree.cb", mainboard);
|
||||||
sprintf(outputc, "%s/static.c", outputdir);
|
char *outputc;
|
||||||
|
|
||||||
headers.next = malloc(sizeof(struct header));
|
if (argc == 3) {
|
||||||
headers.next->name = malloc(strlen(mainboard)+12);
|
scan_mode = STATIC_MODE;
|
||||||
headers.next->next = 0;
|
outputc=malloc(strlen(outputdir)+20);
|
||||||
sprintf(headers.next->name, "mainboard/%s", mainboard);
|
sprintf(outputc, "%s/static.c", outputdir);
|
||||||
|
} else if ((argc == 5) && (argv[3][0] == '-') && (argv[3][2] == 0)) {
|
||||||
|
|
||||||
|
switch (argv[3][1]) {
|
||||||
|
case 's':
|
||||||
|
scan_mode = STATIC_MODE;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
scan_mode = BOOTBLOCK_MODE;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
scan_mode = KCONFIG_MODE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
char *outputfile=argv[4];
|
||||||
|
|
||||||
|
outputc=malloc(strlen(outputdir)+strlen(outputfile)+2);
|
||||||
|
sprintf(outputc, "%s/%s", outputdir, outputfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
headers.next = 0;
|
||||||
|
if (scan_mode == STATIC_MODE) {
|
||||||
|
headers.next = malloc(sizeof(struct header));
|
||||||
|
headers.next->name = malloc(strlen(mainboard)+12);
|
||||||
|
headers.next->next = 0;
|
||||||
|
sprintf(headers.next->name, "mainboard/%s", mainboard);
|
||||||
|
}
|
||||||
|
|
||||||
FILE *filec = fopen(devtree, "r");
|
FILE *filec = fopen(devtree, "r");
|
||||||
if (!filec) {
|
if (!filec) {
|
||||||
|
@ -479,29 +540,67 @@ int main(int argc, char** argv) {
|
||||||
while (head->next != tmp) head = head->next;
|
while (head->next != tmp) head = head->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *staticc = fopen(outputc, "w");
|
FILE *autogen = fopen(outputc, "w");
|
||||||
if (!staticc) {
|
if (!autogen) {
|
||||||
fprintf(stderr, "Could not open file '%s' for writing: ", outputc);
|
fprintf(stderr, "Could not open file '%s' for writing: ", outputc);
|
||||||
perror(NULL);
|
perror(NULL);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(staticc, "#include <device/device.h>\n");
|
struct header *h;
|
||||||
fprintf(staticc, "#include <device/pci.h>\n");
|
if (scan_mode == STATIC_MODE) {
|
||||||
struct header *h = &headers;
|
|
||||||
while (h->next) {
|
fprintf(autogen, "#include <device/device.h>\n");
|
||||||
h = h->next;
|
fprintf(autogen, "#include <device/pci.h>\n");
|
||||||
fprintf(staticc, "#include \"%s/chip.h\"\n", h->name);
|
h = &headers;
|
||||||
|
while (h->next) {
|
||||||
|
h = h->next;
|
||||||
|
fprintf(autogen, "#include \"%s/chip.h\"\n", h->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
walk_device_tree(autogen, &root, inherit_subsystem_ids, NULL);
|
||||||
|
fprintf(autogen, "\n/* pass 0 */\n");
|
||||||
|
walk_device_tree(autogen, &root, pass0, NULL);
|
||||||
|
fprintf(autogen, "\n/* pass 1 */\nstruct mainboard_config mainboard_info_0;\n"
|
||||||
|
"struct device *last_dev = &%s;\n", lastdev->name);
|
||||||
|
walk_device_tree(autogen, &root, pass1, NULL);
|
||||||
|
|
||||||
|
} else if (scan_mode == BOOTBLOCK_MODE) {
|
||||||
|
h = &headers;
|
||||||
|
while (h->next) {
|
||||||
|
h = h->next;
|
||||||
|
fprintf(autogen, "#include \"%s/bootblock.c\"\n", h->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(autogen, "\n#if CONFIG_HAS_MAINBOARD_BOOTBLOCK\n");
|
||||||
|
fprintf(autogen, "#include \"mainboard/%s/bootblock.c\"\n", mainboard);
|
||||||
|
fprintf(autogen, "#else\n");
|
||||||
|
fprintf(autogen, "static unsigned long init_mainboard(int bsp_cpu)\n{\n");
|
||||||
|
fprintf(autogen, "\tif (! bsp_cpu) return 0;\n");
|
||||||
|
h = &headers;
|
||||||
|
while (h->next) {
|
||||||
|
h = h->next;
|
||||||
|
translate_name(h->name, 0);
|
||||||
|
fprintf(autogen, "\tinit_%s();\n", h->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(autogen, "\treturn 0;\n}\n");
|
||||||
|
fprintf(autogen, "#endif\n");
|
||||||
|
|
||||||
|
} else if (scan_mode == KCONFIG_MODE) {
|
||||||
|
fprintf(autogen, "\nconfig MAINBOARD_DIR\n\tstring\n");
|
||||||
|
fprintf(autogen, "\tdefault %s\n", mainboard);
|
||||||
|
|
||||||
|
fprintf(autogen, "\nconfig MAINBOARD_DEVTREE\n\tdef_bool y\n");
|
||||||
|
h = &headers;
|
||||||
|
while (h->next) {
|
||||||
|
h = h->next;
|
||||||
|
translate_name(h->name, 1);
|
||||||
|
fprintf(autogen, "\tselect %s\n", h->name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
walk_device_tree(staticc, &root, inherit_subsystem_ids, NULL);
|
fclose(autogen);
|
||||||
|
|
||||||
fprintf(staticc, "\n/* pass 0 */\n");
|
|
||||||
walk_device_tree(staticc, &root, pass0, NULL);
|
|
||||||
fprintf(staticc, "\n/* pass 1 */\nstruct mainboard_config mainboard_info_0;\nstruct device *last_dev = &%s;\n", lastdev->name);
|
|
||||||
walk_device_tree(staticc, &root, pass1, NULL);
|
|
||||||
|
|
||||||
fclose(staticc);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue