Split C code in sconfig's parser into a separate file.

Update generated parser files.
Add proper include path for utils.

Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>
Acked-by: Peter Stuge <peter@stuge.se>


git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5523 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Patrick Georgi 2010-05-05 11:19:50 +00:00
parent 80da618ab0
commit 114e7b2990
7 changed files with 549 additions and 892 deletions

View File

@ -170,7 +170,7 @@ $(obj)/mainboard/$(MAINBOARDDIR)/static.c: $(src)/mainboard/$(MAINBOARDDIR)/devi
$(objutil)/%.o: $(objutil)/%.c $(objutil)/%.o: $(objutil)/%.c
@printf " HOSTCC $(subst $(objutil)/,,$(@))\n" @printf " HOSTCC $(subst $(objutil)/,,$(@))\n"
$(HOSTCC) -MMD $(HOSTCFLAGS) -c -o $@ $< $(HOSTCC) -MMD -I$(subst $(objutil)/,util/,$(dir $<)) -I$(dir $<) $(HOSTCFLAGS) -c -o $@ $<
$(obj)/%.o: $(obj)/%.c $(obj)/config.h $(obj)/%.o: $(obj)/%.c $(obj)/config.h
@printf " CC $(subst $(obj)/,,$(@))\n" @printf " CC $(subst $(obj)/,,$(@))\n"

View File

@ -1,10 +1,17 @@
sconfigobj := sconfigobj :=
sconfigobj += lex.yy.o sconfigobj += lex.yy.o
sconfigobj += sconfig.tab.o sconfigobj += sconfig.tab.o
sconfigobj += main.o
SCONFIGFLAGS += -I$(top)/util/sconfig -I$(objutil)/sconfig
$(objutil)/sconfig: $(objutil)/sconfig:
mkdir -p $@ mkdir -p $@
$(objutil)/sconfig/%.o: util/sconfig/%.c
printf " HOSTCC $(subst $(obj)/,,$(@))\n"
$(HOSTCC) $(SCONFIGFLAGS) $(HOSTCFLAGS) -c -o $@ $<
$(objutil)/sconfig/%.o: $(objutil)/sconfig/%.c $(objutil)/sconfig/%.o: $(objutil)/sconfig/%.c
printf " HOSTCC $(subst $(obj)/,,$(@))\n" printf " HOSTCC $(subst $(obj)/,,$(@))\n"
$(HOSTCC) $(SCONFIGFLAGS) $(HOSTCFLAGS) -c -o $@ $< $(HOSTCC) $(SCONFIGFLAGS) $(HOSTCFLAGS) -c -o $@ $<

417
util/sconfig/main.c Executable file
View File

@ -0,0 +1,417 @@
/*
* sconfig, coreboot device tree compiler
*
* Copyright (C) 2010 coresystems GmbH
* written by Patrick Georgi <patrick.georgi@coresystems.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
*/
#include "sconfig.h"
#include "sconfig.tab.h"
struct device *head, *lastdev;
struct header headers;
static int devcount = 0;
static struct device root;
static struct device mainboard = {
.name = "mainboard",
.name_underscore = "mainboard",
.id = 0,
.chip = &mainboard,
.type = chip,
.chiph_exists = 1,
.children = &root
};
static struct device root = {
.name = "dev_root",
.name_underscore = "dev_root",
.id = 0,
.chip = &mainboard,
.type = device,
.path = " .type = DEVICE_PATH_ROOT ",
.ops = "&default_dev_ops_root",
.parent = &root,
.bus = &root,
.enabled = 1
};
static struct device *new_dev() {
struct device *dev = malloc(sizeof(struct device));
memset(dev, 0, sizeof(struct device));
dev->id = ++devcount;
dev->parent = cur_parent;
dev->bus = cur_bus;
head->next = dev;
head = dev;
return dev;
}
static int device_match(struct device *a, struct device *b) {
if ((a->bustype == b->bustype) && (a->bus == b->bus) && (a->path_a == b->path_a) && (a->path_b == b->path_b))
return 1;
return 0;
}
void fold_in(struct device *parent) {
struct device *child = parent->children;
struct device *latest = 0;
while (child != latest) {
if (child->children) {
if (!latest) latest = child->children;
parent->latestchild->next_sibling = child->children;
parent->latestchild = child->latestchild;
}
child = child->next_sibling;
}
}
int yywrap(void) {
return 1;
}
void yyerror (char const *str)
{
fprintf (stderr, "%s\n", str);
}
void postprocess_devtree(void) {
root.next_sibling = root.children;
root.next_sibling->next_sibling = root.next_sibling->children;
struct device *dev = &root;
while (dev) {
/* skip "chip" elements in children chain */
while (dev->children && (dev->children->type == chip)) dev->children = dev->children->children;
/* skip "chip" elements and functions of the same device in sibling chain */
while (dev->sibling && dev->sibling->used) dev->sibling = dev->sibling->sibling;
/* If end of chain, and parent is a chip, move on */
if (!dev->sibling && (dev->parent->type == chip)) dev->sibling = dev->parent->sibling;
/* skip chips */
while (dev->sibling && dev->sibling->type == chip) dev->sibling = dev->sibling->children;
/* skip duplicate function elements in nextdev chain */
while (dev->nextdev && dev->nextdev->used) dev->nextdev = dev->nextdev->nextdev;
dev = dev->next_sibling;
}
}
struct device *new_chip(char *path) {
struct device *new_chip = new_dev();
new_chip->chiph_exists = 1;
new_chip->name = path;
new_chip->name_underscore = strdup(new_chip->name);
char *c;
for (c = new_chip->name_underscore; *c; c++) {
if (*c == '/') *c = '_';
if (*c == '-') *c = '_';
}
new_chip->type = chip;
new_chip->chip = new_chip;
struct stat st;
char *chip_h = malloc(strlen(path)+12);
sprintf(chip_h, "src/%s/chip.h", path);
if ((stat(chip_h, &st) == -1) && (errno == ENOENT))
new_chip->chiph_exists = 0;
if (cur_parent->latestchild) {
cur_parent->latestchild->next_sibling = new_chip;
cur_parent->latestchild->sibling = new_chip;
}
cur_parent->latestchild = new_chip;
if (!cur_parent->children)
cur_parent->children = new_chip;
return new_chip;
}
void add_header(struct device *dev) {
if (dev->chiph_exists) {
int include_exists = 0;
struct header *h = &headers;
while (h->next) {
int result = strcmp(dev->name, h->next->name);
if (result == 0) {
include_exists = 1;
break;
}
if (result < 0) break;
h = h->next;
}
if (!include_exists) {
struct header *tmp = h->next;
h->next = malloc(sizeof(struct header));
memset(h->next, 0, sizeof(struct header));
h->next->name = dev->name;
h->next->next = tmp;
}
}
}
struct device *new_device(const int bus, const char *devnum, int enabled) {
struct device *new_d = new_dev();
new_d->bustype = bus;
char *tmp;
new_d->path_a = strtol(strdup(devnum), &tmp, 16);
if (*tmp == '.') {
tmp++;
new_d->path_b = strtol(tmp, NULL, 16);
}
char *name = malloc(10);
sprintf(name, "_dev%d", new_d->id);
new_d->name = name;
new_d->name_underscore = name; // shouldn't be necessary, but avoid 0-ptr
new_d->type = device;
new_d->enabled = enabled;
new_d->chip = new_d->parent->chip;
if (cur_parent->latestchild) {
cur_parent->latestchild->next_sibling = new_d;
cur_parent->latestchild->sibling = new_d;
}
cur_parent->latestchild = new_d;
if (!cur_parent->children)
cur_parent->children = new_d;
lastdev->nextdev = new_d;
lastdev = new_d;
if (bus == PCI) {
new_d->path = ".type=DEVICE_PATH_PCI,{.pci={ .devfn = PCI_DEVFN(0x%x,%d)}}";
}
if (bus == PNP) {
new_d->path = ".type=DEVICE_PATH_PNP,{.pnp={ .port = 0x%x, .device = 0x%x }}";
}
if (bus == I2C) {
new_d->path = ".type=DEVICE_PATH_I2C,{.i2c={ .device = 0x%x }}";
}
if (bus == APIC) {
new_d->path = ".type=DEVICE_PATH_APIC,{.apic={ .apic_id = 0x%x }}";
}
if (bus == APIC_CLUSTER) {
new_d->path = ".type=DEVICE_PATH_APIC_CLUSTER,{.apic_cluster={ .cluster = 0x%x }}";
}
if (bus == PCI_DOMAIN) {
new_d->path = ".type=DEVICE_PATH_PCI_DOMAIN,{.pci_domain={ .domain = 0x%x }}";
}
return new_d;
}
void alias_siblings(struct device *d) {
while (d) {
int link = 0;
struct device *cmp = d->next_sibling;
while (cmp && (cmp->bus == d->bus) && (cmp->path_a == d->path_a) && (cmp->path_b == d->path_b)) {
if (cmp->type==device && !cmp->used) {
if (device_match(d, cmp)) {
d->multidev = 1;
cmp->aliased_name = malloc(12);
sprintf(cmp->aliased_name, "_dev%d", cmp->id);
cmp->id = d->id;
cmp->name = d->name;
cmp->used = 1;
cmp->link = ++link;
}
}
cmp = cmp->next_sibling;
}
d = d->next_sibling;
}
}
void add_resource(int type, int index, int base) {
struct resource *r = malloc(sizeof(struct resource));
memset (r, 0, sizeof(struct resource));
r->type = type;
r->index = index;
r->base = base;
if (cur_parent->res) {
struct resource *head = cur_parent->res;
while (head->next) head = head->next;
head->next = r;
} else {
cur_parent->res = r;
}
cur_parent->rescnt++;
}
void add_register(char *name, char *val) {
struct reg *r = malloc(sizeof(struct reg));
memset (r, 0, sizeof(struct reg));
r->key = name;
r->value = val;
if (cur_parent->reg) {
struct reg *head = cur_parent->reg;
// sorting to be equal to sconfig's behaviour
int sort = strcmp(r->key, head->key);
if (sort == 0) {
printf("ERROR: duplicate 'register' key.\n");
exit(1);
}
if (sort<0) {
r->next = head;
cur_parent->reg = r;
} else {
while ((head->next) && (strcmp(head->next->key, r->key)<0)) head = head->next;
r->next = head->next;
head->next = r;
}
} else {
cur_parent->reg = r;
}
}
static void pass0(FILE *fil, struct device *ptr) {
if ((ptr->type == device) && (ptr->id != 0) && (!ptr->used))
fprintf(fil, "struct device %s;\n", ptr->name);
if ((ptr->type == device) && (ptr->id != 0) && ptr->used)
fprintf(fil, "struct device %s;\n", ptr->aliased_name);
}
static void pass1(FILE *fil, struct device *ptr) {
if (!ptr->used && (ptr->type == device)) {
fprintf(fil, "struct device %s = {\n", ptr->name);
fprintf(fil, "\t.ops = %s,\n", (ptr->ops)?(ptr->ops):"0");
fprintf(fil, "\t.bus = &%s.link[%d],\n", ptr->bus->name, ptr->bus->link);
fprintf(fil, "\t.path = {");
fprintf(fil, ptr->path, ptr->path_a, ptr->path_b);
fprintf(fil, "},\n");
fprintf(fil, "\t.enabled = %d,\n", ptr->enabled);
fprintf(fil, "\t.on_mainboard = 1,\n");
if (ptr->rescnt > 0) {
fprintf(fil, "\t.resources = %d,\n", ptr->rescnt);
fprintf(fil, "\t.resource = {\n");
struct resource *r = ptr->res;
while (r) {
fprintf(fil, "\t\t{ .flags=IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_");
if (r->type == IRQ) fprintf(fil, "IRQ");
if (r->type == DRQ) fprintf(fil, "DRQ");
if (r->type == IO) fprintf(fil, "IO");
fprintf(fil, ", .index=0x%x, .base=0x%x},\n", r->index, r->base);
r = r->next;
}
fprintf(fil, "\t },\n");
}
int link = 0;
fprintf(fil, "\t.link = {\n");
if (ptr->multidev) {
struct device *d = ptr;
while (d) {
if (device_match(d, ptr)) {
fprintf(fil, "\t\t[%d] = {\n", d->link);
fprintf(fil, "\t\t\t.link = %d,\n", d->link);
fprintf(fil, "\t\t\t.dev = &%s,\n", d->name);
if (d->children)
fprintf(fil, "\t\t\t.children = &%s,\n", d->children->name);
fprintf(fil, "\t\t},\n");
link++;
}
d = d->next_sibling;
}
} else {
if (ptr->children) {
fprintf(fil, "\t\t[0] = {\n");
fprintf(fil, "\t\t\t.link = 0,\n");
fprintf(fil, "\t\t\t.dev = &%s,\n", ptr->name);
fprintf(fil, "\t\t\t.children = &%s,\n", ptr->children->name);
fprintf(fil, "\t\t},\n");
link++;
}
}
fprintf(fil, "\t},\n");
fprintf(fil, "\t.links = %d,\n", link);
if (ptr->sibling)
fprintf(fil, "\t.sibling = &%s,\n", ptr->sibling->name);
if (ptr->chip->chiph_exists) {
fprintf(fil, "\t.chip_ops = &%s_ops,\n", ptr->chip->name_underscore);
fprintf(fil, "\t.chip_info = &%s_info_%d,\n", ptr->chip->name_underscore, ptr->chip->id);
}
if (ptr->nextdev)
fprintf(fil, "\t.next=&%s\n", ptr->nextdev->name);
fprintf(fil, "};\n");
}
if ((ptr->type == chip) && (ptr->chiph_exists)) {
if (ptr->reg) {
fprintf(fil, "struct %s_config %s_info_%d\t= {\n", ptr->name_underscore, ptr->name_underscore, ptr->id);
struct reg *r = ptr->reg;
while (r) {
fprintf(fil, "\t.%s = %s,\n", r->key, r->value);
r = r->next;
}
fprintf(fil, "};\n\n");
} else {
fprintf(fil, "struct %s_config %s_info_%d;\n", ptr->name_underscore, ptr->name_underscore, ptr->id);
}
}
}
static void walk_device_tree(FILE *fil, struct device *ptr, void (*func)(FILE *, struct device*), struct device *chips) {
do {
func(fil, ptr);
ptr = ptr->next_sibling;
} while (ptr);
}
int main(int argc, char** argv) {
if (argc != 3) {
printf("usage: sconfig vendor/mainboard outputdir\n");
return 1;
}
char *mainboard=argv[1];
char *outputdir=argv[2];
char *devtree=malloc(strlen(mainboard)+30);
char *outputc=malloc(strlen(outputdir)+10);
sprintf(devtree, "src/mainboard/%s/devicetree.cb", mainboard);
sprintf(outputc, "%s/static.c", outputdir);
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");
yyrestart(filec);
FILE *staticc = fopen(outputc, "w");
cur_bus = cur_parent = lastdev = head = &root;
yyparse();
fclose(filec);
if ((head->type == chip) && (!head->chiph_exists)) {
struct device *tmp = head;
head = &root;
while (head->next != tmp) head = head->next;
}
fprintf(staticc, "#include <device/device.h>\n");
fprintf(staticc, "#include <device/pci.h>\n");
struct header *h = &headers;
while (h->next) {
h = h->next;
fprintf(staticc, "#include \"%s/chip.h\"\n", h->name);
}
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_p = &%s.next;\n", lastdev->name);
walk_device_tree(staticc, &root, pass1, NULL);
fclose(staticc);
return 0;
}

93
util/sconfig/sconfig.h Executable file
View File

@ -0,0 +1,93 @@
/*
* sconfig, coreboot device tree compiler
*
* Copyright (C) 2010 coresystems GmbH
* written by Patrick Georgi <patrick.georgi@coresystems.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
enum devtype { chip, device };
struct resource;
struct resource {
int type;
int index;
int base;
struct resource *next;
};
struct reg;
struct reg {
char *key;
char *value;
struct reg *next;
};
struct device;
struct device {
int id;
int enabled;
int used;
int multidev;
int link;
int rescnt;
int chiph_exists;
char *ops;
char *name;
char *aliased_name;
char *name_underscore;
char *path;
int path_a;
int path_b;
int bustype;
enum devtype type;
struct device *parent;
struct device *bus;
struct device *next;
struct device *nextdev;
struct device *children;
struct device *latestchild;
struct device *next_sibling;
struct device *sibling;
struct device *chip;
struct resource *res;
struct reg *reg;
};
extern struct device *cur_parent, *cur_bus;
struct header;
struct header {
char *name;
struct header *next;
};
void fold_in(struct device *parent);
void postprocess_devtree(void);
struct device *new_chip(char *path);
void add_header(struct device *dev);
struct device *new_device(const int bus, const char *devnum, int enabled);
void alias_siblings(struct device *d);
void add_resource(int type, int index, int base);
void add_register(char *name, char *val);

View File

@ -2,20 +2,20 @@
/* A Bison parser, made by GNU Bison 2.4.1. */ /* A Bison parser, made by GNU Bison 2.4.1. */
/* Skeleton implementation for Bison's Yacc-like parsers in C /* Skeleton implementation for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc. Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */ along with this program. If not, see <http://www.gnu.org/licenses/>. */
@ -28,7 +28,7 @@
special exception, which will cause the skeleton and the resulting special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public Bison output files to be licensed under the GNU General Public
License without this special exception. License without this special exception.
This special exception was added by the Free Software Foundation in This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */ version 2.2 of Bison. */
@ -88,108 +88,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
*/ */
#include <stdio.h> #include "sconfig.h"
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
enum devtype { chip, device }; struct device *cur_parent, *cur_bus;
struct resource;
struct resource {
int type;
int index;
int base;
struct resource *next;
};
struct reg;
struct reg {
char *key;
char *value;
struct reg *next;
};
struct device;
struct device {
int id;
int enabled;
int used;
int multidev;
int link;
int rescnt;
int chiph_exists;
char *ops;
char *name;
char *aliased_name;
char *name_underscore;
char *path;
int path_a;
int path_b;
int bustype;
enum devtype type;
struct device *parent;
struct device *bus;
struct device *next;
struct device *nextdev;
struct device *children;
struct device *latestchild;
struct device *next_sibling;
struct device *sibling;
struct device *chip;
struct resource *res;
struct reg *reg;
} *head, *lastdev, *cur_parent, *cur_bus, root;
struct header;
struct header {
char *name;
struct header *next;
} headers;
int devcount = 0;
struct device *new_dev() {
struct device *dev = malloc(sizeof(struct device));
memset(dev, 0, sizeof(struct device));
dev->id = ++devcount;
dev->parent = cur_parent;
dev->bus = cur_bus;
head->next = dev;
head = dev;
return dev;
}
int device_match(struct device *a, struct device *b) {
if ((a->bustype == b->bustype) && (a->bus == b->bus) && (a->path_a == b->path_a) && (a->path_b == b->path_b))
return 1;
return 0;
}
void fold_in(struct device *parent) {
struct device *child = parent->children;
struct device *latest = 0;
while (child != latest) {
if (child->children) {
if (!latest) latest = child->children;
parent->latestchild->next_sibling = child->children;
parent->latestchild = child->latestchild;
}
child = child->next_sibling;
}
}
int yywrap(void) {
return 1;
}
void yyerror (char const *str)
{
fprintf (stderr, "%s\n", str);
}
@ -549,10 +451,10 @@ static const yytype_int8 yyrhs[] =
}; };
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ /* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] = static const yytype_uint8 yyrline[] =
{ {
0, 132, 132, 152, 152, 154, 154, 154, 156, 156, 0, 34, 34, 36, 36, 38, 38, 38, 40, 40,
156, 158, 158, 215, 215, 294, 312 40, 42, 42, 52, 52, 64, 67
}; };
#endif #endif
@ -1466,56 +1368,13 @@ yyreduce:
{ {
case 2: case 2:
{ { postprocess_devtree(); ;}
root.next_sibling = root.children;
root.next_sibling->next_sibling = root.next_sibling->children;
struct device *dev = &root;
while (dev) {
/* skip "chip" elements in children chain */
while (dev->children && (dev->children->type == chip)) dev->children = dev->children->children;
/* skip "chip" elements and functions of the same device in sibling chain */
while (dev->sibling && dev->sibling->used) dev->sibling = dev->sibling->sibling;
/* If end of chain, and parent is a chip, move on */
if (!dev->sibling && (dev->parent->type == chip)) dev->sibling = dev->parent->sibling;
/* skip chips */
while (dev->sibling && dev->sibling->type == chip) dev->sibling = dev->sibling->children;
/* skip duplicate function elements in nextdev chain */
while (dev->nextdev && dev->nextdev->used) dev->nextdev = dev->nextdev->nextdev;
dev = dev->next_sibling;
}
;}
break; break;
case 11: case 11:
{ {
(yyval.device) = new_dev(); (yyval.device) = new_chip((yyvsp[(2) - (2)].string));
(yyval.device)->chiph_exists = 1;
(yyval.device)->name = (yyvsp[(2) - (2)].string);
(yyval.device)->name_underscore = strdup((yyval.device)->name);
char *c;
for (c = (yyval.device)->name_underscore; *c; c++) {
if (*c == '/') *c = '_';
if (*c == '-') *c = '_';
}
(yyval.device)->type = chip;
(yyval.device)->chip = (yyval.device);
struct stat st;
char *chip_h = malloc(strlen((yyvsp[(2) - (2)].string))+12);
sprintf(chip_h, "src/%s/chip.h", (yyvsp[(2) - (2)].string));
if ((stat(chip_h, &st) == -1) && (errno == ENOENT))
(yyval.device)->chiph_exists = 0;
if (cur_parent->latestchild) {
cur_parent->latestchild->next_sibling = (yyval.device);
cur_parent->latestchild->sibling = (yyval.device);
}
cur_parent->latestchild = (yyval.device);
if (!cur_parent->children)
cur_parent->children = (yyval.device);
cur_parent = (yyval.device); cur_parent = (yyval.device);
;} ;}
break; break;
@ -1524,82 +1383,15 @@ yyreduce:
{ {
cur_parent = (yyvsp[(3) - (5)].device)->parent; cur_parent = (yyvsp[(3) - (5)].device)->parent;
fold_in((yyvsp[(3) - (5)].device)); fold_in((yyvsp[(3) - (5)].device));
add_header((yyvsp[(3) - (5)].device));
if ((yyvsp[(3) - (5)].device)->chiph_exists) {
int include_exists = 0;
struct header *h = &headers;
while (h->next) {
int result = strcmp((yyvsp[(3) - (5)].device)->name, h->next->name);
if (result == 0) {
include_exists = 1;
break;
}
if (result < 0) break;
h = h->next;
}
if (!include_exists) {
struct header *tmp = h->next;
h->next = malloc(sizeof(struct header));
memset(h->next, 0, sizeof(struct header));
h->next->name = (yyvsp[(3) - (5)].device)->name;
h->next->next = tmp;
break;
}
}
;} ;}
break; break;
case 13: case 13:
{ {
(yyval.device) = new_dev(); (yyval.device) = new_device((yyvsp[(2) - (4)].number), (yyvsp[(3) - (4)].string), (yyvsp[(4) - (4)].number));
(yyval.device)->bustype = (yyvsp[(2) - (4)].number);
char *tmp;
(yyval.device)->path_a = strtol(strdup((yyvsp[(3) - (4)].string)), &tmp, 16);
if (*tmp == '.') {
tmp++;
(yyval.device)->path_b = strtol(tmp, NULL, 16);
}
char *name = malloc(10);
sprintf(name, "_dev%d", (yyval.device)->id);
(yyval.device)->name = name;
(yyval.device)->name_underscore = name; // shouldn't be necessary, but avoid 0-ptr
(yyval.device)->type = device;
(yyval.device)->enabled = (yyvsp[(4) - (4)].number);
(yyval.device)->chip = (yyval.device)->parent->chip;
if (cur_parent->latestchild) {
cur_parent->latestchild->next_sibling = (yyval.device);
cur_parent->latestchild->sibling = (yyval.device);
}
cur_parent->latestchild = (yyval.device);
if (!cur_parent->children)
cur_parent->children = (yyval.device);
lastdev->nextdev = (yyval.device);
lastdev = (yyval.device);
if ((yyvsp[(2) - (4)].number) == PCI) {
(yyval.device)->path = ".type=DEVICE_PATH_PCI,{.pci={ .devfn = PCI_DEVFN(0x%x,%d)}}";
}
if ((yyvsp[(2) - (4)].number) == PNP) {
(yyval.device)->path = ".type=DEVICE_PATH_PNP,{.pnp={ .port = 0x%x, .device = 0x%x }}";
}
if ((yyvsp[(2) - (4)].number) == I2C) {
(yyval.device)->path = ".type=DEVICE_PATH_I2C,{.i2c={ .device = 0x%x }}";
}
if ((yyvsp[(2) - (4)].number) == APIC) {
(yyval.device)->path = ".type=DEVICE_PATH_APIC,{.apic={ .apic_id = 0x%x }}";
}
if ((yyvsp[(2) - (4)].number) == APIC_CLUSTER) {
(yyval.device)->path = ".type=DEVICE_PATH_APIC_CLUSTER,{.apic_cluster={ .cluster = 0x%x }}";
}
if ((yyvsp[(2) - (4)].number) == PCI_DOMAIN) {
(yyval.device)->path = ".type=DEVICE_PATH_PCI_DOMAIN,{.pci_domain={ .domain = 0x%x }}";
}
cur_parent = (yyval.device); cur_parent = (yyval.device);
cur_bus = (yyval.device); cur_bus = (yyval.device);
;} ;}
@ -1610,79 +1402,19 @@ yyreduce:
{ {
cur_parent = (yyvsp[(5) - (7)].device)->parent; cur_parent = (yyvsp[(5) - (7)].device)->parent;
cur_bus = (yyvsp[(5) - (7)].device)->bus; cur_bus = (yyvsp[(5) - (7)].device)->bus;
fold_in((yyvsp[(5) - (7)].device)); fold_in((yyvsp[(5) - (7)].device));
alias_siblings((yyvsp[(5) - (7)].device)->children);
struct device *d = (yyvsp[(5) - (7)].device)->children;
while (d) {
int link = 0;
struct device *cmp = d->next_sibling;
while (cmp && (cmp->bus == d->bus) && (cmp->path_a == d->path_a) && (cmp->path_b == d->path_b)) {
if (cmp->type==device && !cmp->used) {
if (device_match(d, cmp)) {
d->multidev = 1;
cmp->aliased_name = malloc(12);
sprintf(cmp->aliased_name, "_dev%d", cmp->id);
cmp->id = d->id;
cmp->name = d->name;
cmp->used = 1;
cmp->link = ++link;
}
}
cmp = cmp->next_sibling;
}
d = d->next_sibling;
}
;} ;}
break; break;
case 15: case 15:
{ { add_resource((yyvsp[(1) - (4)].number), strtol((yyvsp[(2) - (4)].string), NULL, 0), strtol((yyvsp[(4) - (4)].string), NULL, 0)); ;}
struct resource *r = malloc(sizeof(struct resource));
memset (r, 0, sizeof(struct resource));
r->type = (yyvsp[(1) - (4)].number);
r->index = strtol((yyvsp[(2) - (4)].string), NULL, 0);
r->base = strtol((yyvsp[(4) - (4)].string), NULL, 0);
if (cur_parent->res) {
struct resource *head = cur_parent->res;
while (head->next) head = head->next;
head->next = r;
} else {
cur_parent->res = r;
}
cur_parent->rescnt++;
;}
break; break;
case 16: case 16:
{ { add_register((yyvsp[(2) - (4)].string), (yyvsp[(4) - (4)].string)); ;}
struct reg *r = malloc(sizeof(struct reg));
memset (r, 0, sizeof(struct reg));
r->key = (yyvsp[(2) - (4)].string);
r->value = (yyvsp[(4) - (4)].string);
if (cur_parent->reg) {
struct reg *head = cur_parent->reg;
// sorting to be equal to sconfig's behaviour
int sort = strcmp(r->key, head->key);
if (sort == 0) {
printf("ERROR: duplicate 'register' key.\n");
exit(1);
}
if (sort<0) {
r->next = head;
cur_parent->reg = r;
} else {
while ((head->next) && (strcmp(head->next->key, r->key)<0)) head = head->next;
r->next = head->next;
head->next = r;
}
} else {
cur_parent->reg = r;
}
;}
break; break;
@ -1898,165 +1630,4 @@ yyreturn:
void pass0(FILE *fil, struct device *ptr) {
if ((ptr->type == device) && (ptr->id != 0) && (!ptr->used))
fprintf(fil, "struct device %s;\n", ptr->name);
if ((ptr->type == device) && (ptr->id != 0) && ptr->used)
fprintf(fil, "struct device %s;\n", ptr->aliased_name);
}
void pass1(FILE *fil, struct device *ptr) {
if (!ptr->used && (ptr->type == device)) {
fprintf(fil, "struct device %s = {\n", ptr->name);
fprintf(fil, "\t.ops = %s,\n", (ptr->ops)?(ptr->ops):"0");
fprintf(fil, "\t.bus = &%s.link[%d],\n", ptr->bus->name, ptr->bus->link);
fprintf(fil, "\t.path = {");
fprintf(fil, ptr->path, ptr->path_a, ptr->path_b);
fprintf(fil, "},\n");
fprintf(fil, "\t.enabled = %d,\n", ptr->enabled);
fprintf(fil, "\t.on_mainboard = 1,\n");
if (ptr->rescnt > 0) {
fprintf(fil, "\t.resources = %d,\n", ptr->rescnt);
fprintf(fil, "\t.resource = {\n");
struct resource *r = ptr->res;
while (r) {
fprintf(fil, "\t\t{ .flags=IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_");
if (r->type == IRQ) fprintf(fil, "IRQ");
if (r->type == DRQ) fprintf(fil, "DRQ");
if (r->type == IO) fprintf(fil, "IO");
fprintf(fil, ", .index=0x%x, .base=0x%x},\n", r->index, r->base);
r = r->next;
}
fprintf(fil, "\t },\n");
}
int link = 0;
fprintf(fil, "\t.link = {\n");
if (ptr->multidev) {
struct device *d = ptr;
while (d) {
if (device_match(d, ptr)) {
fprintf(fil, "\t\t[%d] = {\n", d->link);
fprintf(fil, "\t\t\t.link = %d,\n", d->link);
fprintf(fil, "\t\t\t.dev = &%s,\n", d->name);
if (d->children)
fprintf(fil, "\t\t\t.children = &%s,\n", d->children->name);
fprintf(fil, "\t\t},\n");
link++;
}
d = d->next_sibling;
}
} else {
if (ptr->children) {
fprintf(fil, "\t\t[0] = {\n");
fprintf(fil, "\t\t\t.link = 0,\n");
fprintf(fil, "\t\t\t.dev = &%s,\n", ptr->name);
fprintf(fil, "\t\t\t.children = &%s,\n", ptr->children->name);
fprintf(fil, "\t\t},\n");
link++;
}
}
fprintf(fil, "\t},\n");
fprintf(fil, "\t.links = %d,\n", link);
if (ptr->sibling)
fprintf(fil, "\t.sibling = &%s,\n", ptr->sibling->name);
if (ptr->chip->chiph_exists) {
fprintf(fil, "\t.chip_ops = &%s_ops,\n", ptr->chip->name_underscore);
fprintf(fil, "\t.chip_info = &%s_info_%d,\n", ptr->chip->name_underscore, ptr->chip->id);
}
if (ptr->nextdev)
fprintf(fil, "\t.next=&%s\n", ptr->nextdev->name);
fprintf(fil, "};\n");
}
if ((ptr->type == chip) && (ptr->chiph_exists)) {
if (ptr->reg) {
fprintf(fil, "struct %s_config %s_info_%d\t= {\n", ptr->name_underscore, ptr->name_underscore, ptr->id);
struct reg *r = ptr->reg;
while (r) {
fprintf(fil, "\t.%s = %s,\n", r->key, r->value);
r = r->next;
}
fprintf(fil, "};\n\n");
} else {
fprintf(fil, "struct %s_config %s_info_%d;\n", ptr->name_underscore, ptr->name_underscore, ptr->id);
}
}
}
void walk_device_tree(FILE *fil, struct device *ptr, void (*func)(FILE *, struct device*), struct device *chips) {
do {
func(fil, ptr);
ptr = ptr->next_sibling;
} while (ptr);
}
struct device mainboard = {
.name = "mainboard",
.name_underscore = "mainboard",
.id = 0,
.chip = &mainboard,
.type = chip,
.chiph_exists = 1,
.children = &root
};
struct device root = {
.name = "dev_root",
.name_underscore = "dev_root",
.id = 0,
.chip = &mainboard,
.type = device,
.path = " .type = DEVICE_PATH_ROOT ",
.ops = "&default_dev_ops_root",
.parent = &root,
.bus = &root,
.enabled = 1
};
int main(int argc, char** argv) {
if (argc != 3) {
printf("usage: sconfig vendor/mainboard outputdir\n");
return 1;
}
char *mainboard=argv[1];
char *outputdir=argv[2];
char *devtree=malloc(strlen(mainboard)+30);
char *outputc=malloc(strlen(outputdir)+10);
sprintf(devtree, "src/mainboard/%s/devicetree.cb", mainboard);
sprintf(outputc, "%s/static.c", outputdir);
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");
yyrestart(filec);
FILE *staticc = fopen(outputc, "w");
cur_bus = cur_parent = lastdev = head = &root;
yyparse();
fclose(filec);
if ((head->type == chip) && (!head->chiph_exists)) {
struct device *tmp = head;
head = &root;
while (head->next != tmp) head = head->next;
}
fprintf(staticc, "#include <device/device.h>\n");
fprintf(staticc, "#include <device/pci.h>\n");
struct header *h = &headers;
while (h->next) {
h = h->next;
fprintf(staticc, "#include \"%s/chip.h\"\n", h->name);
}
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_p = &%s.next;\n", lastdev->name);
walk_device_tree(staticc, &root, pass1, NULL);
fclose(staticc);
return 0;
}

View File

@ -2,20 +2,20 @@
/* A Bison parser, made by GNU Bison 2.4.1. */ /* A Bison parser, made by GNU Bison 2.4.1. */
/* Skeleton interface for Bison's Yacc-like parsers in C /* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc. Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */ along with this program. If not, see <http://www.gnu.org/licenses/>. */
@ -28,7 +28,7 @@
special exception, which will cause the skeleton and the resulting special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public Bison output files to be licensed under the GNU General Public
License without this special exception. License without this special exception.
This special exception was added by the Free Software Foundation in This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */ version 2.2 of Bison. */

View File

@ -19,108 +19,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
*/ */
#include <stdio.h> #include "sconfig.h"
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
enum devtype { chip, device }; struct device *cur_parent, *cur_bus;
struct resource;
struct resource {
int type;
int index;
int base;
struct resource *next;
};
struct reg;
struct reg {
char *key;
char *value;
struct reg *next;
};
struct device;
struct device {
int id;
int enabled;
int used;
int multidev;
int link;
int rescnt;
int chiph_exists;
char *ops;
char *name;
char *aliased_name;
char *name_underscore;
char *path;
int path_a;
int path_b;
int bustype;
enum devtype type;
struct device *parent;
struct device *bus;
struct device *next;
struct device *nextdev;
struct device *children;
struct device *latestchild;
struct device *next_sibling;
struct device *sibling;
struct device *chip;
struct resource *res;
struct reg *reg;
} *head, *lastdev, *cur_parent, *cur_bus, root;
struct header;
struct header {
char *name;
struct header *next;
} headers;
int devcount = 0;
struct device *new_dev() {
struct device *dev = malloc(sizeof(struct device));
memset(dev, 0, sizeof(struct device));
dev->id = ++devcount;
dev->parent = cur_parent;
dev->bus = cur_bus;
head->next = dev;
head = dev;
return dev;
}
int device_match(struct device *a, struct device *b) {
if ((a->bustype == b->bustype) && (a->bus == b->bus) && (a->path_a == b->path_a) && (a->path_b == b->path_b))
return 1;
return 0;
}
void fold_in(struct device *parent) {
struct device *child = parent->children;
struct device *latest = 0;
while (child != latest) {
if (child->children) {
if (!latest) latest = child->children;
parent->latestchild->next_sibling = child->children;
parent->latestchild = child->latestchild;
}
child = child->next_sibling;
}
}
int yywrap(void) {
return 1;
}
void yyerror (char const *str)
{
fprintf (stderr, "%s\n", str);
}
%} %}
%union { %union {
struct device *device; struct device *device;
@ -129,25 +31,7 @@ void yyerror (char const *str)
} }
%token CHIP DEVICE REGISTER BOOL BUS RESOURCE END EQUALS HEX STRING PCI PNP I2C APIC APIC_CLUSTER PCI_DOMAIN IRQ DRQ IO NUMBER %token CHIP DEVICE REGISTER BOOL BUS RESOURCE END EQUALS HEX STRING PCI PNP I2C APIC APIC_CLUSTER PCI_DOMAIN IRQ DRQ IO NUMBER
%% %%
devtree: devchip { devtree: devchip { postprocess_devtree(); } ;
root.next_sibling = root.children;
root.next_sibling->next_sibling = root.next_sibling->children;
struct device *dev = &root;
while (dev) {
/* skip "chip" elements in children chain */
while (dev->children && (dev->children->type == chip)) dev->children = dev->children->children;
/* skip "chip" elements and functions of the same device in sibling chain */
while (dev->sibling && dev->sibling->used) dev->sibling = dev->sibling->sibling;
/* If end of chain, and parent is a chip, move on */
if (!dev->sibling && (dev->parent->type == chip)) dev->sibling = dev->parent->sibling;
/* skip chips */
while (dev->sibling && dev->sibling->type == chip) dev->sibling = dev->sibling->children;
/* skip duplicate function elements in nextdev chain */
while (dev->nextdev && dev->nextdev->used) dev->nextdev = dev->nextdev->nextdev;
dev = dev->next_sibling;
}
};
devchip: chip | device ; devchip: chip | device ;
@ -156,346 +40,31 @@ devices: devices devchip | devices registers | ;
devicesorresources: devicesorresources devchip | devicesorresources resource | ; devicesorresources: devicesorresources devchip | devicesorresources resource | ;
chip: CHIP STRING /* == path */ { chip: CHIP STRING /* == path */ {
$<device>$ = new_dev(); $<device>$ = new_chip($<string>2);
$<device>$->chiph_exists = 1;
$<device>$->name = $<string>2;
$<device>$->name_underscore = strdup($<device>$->name);
char *c;
for (c = $<device>$->name_underscore; *c; c++) {
if (*c == '/') *c = '_';
if (*c == '-') *c = '_';
}
$<device>$->type = chip;
$<device>$->chip = $<device>$;
struct stat st;
char *chip_h = malloc(strlen($<string>2)+12);
sprintf(chip_h, "src/%s/chip.h", $<string>2);
if ((stat(chip_h, &st) == -1) && (errno == ENOENT))
$<device>$->chiph_exists = 0;
if (cur_parent->latestchild) {
cur_parent->latestchild->next_sibling = $<device>$;
cur_parent->latestchild->sibling = $<device>$;
}
cur_parent->latestchild = $<device>$;
if (!cur_parent->children)
cur_parent->children = $<device>$;
cur_parent = $<device>$; cur_parent = $<device>$;
} }
devices END { devices END {
cur_parent = $<device>3->parent; cur_parent = $<device>3->parent;
fold_in($<device>3); fold_in($<device>3);
add_header($<device>3);
if ($<device>3->chiph_exists) {
int include_exists = 0;
struct header *h = &headers;
while (h->next) {
int result = strcmp($<device>3->name, h->next->name);
if (result == 0) {
include_exists = 1;
break;
}
if (result < 0) break;
h = h->next;
}
if (!include_exists) {
struct header *tmp = h->next;
h->next = malloc(sizeof(struct header));
memset(h->next, 0, sizeof(struct header));
h->next->name = $<device>3->name;
h->next->next = tmp;
break;
}
}
}; };
device: DEVICE BUS NUMBER /* == devnum */ BOOL { device: DEVICE BUS NUMBER /* == devnum */ BOOL {
$<device>$ = new_dev(); $<device>$ = new_device($<number>2, $<string>3, $<number>4);
$<device>$->bustype = $<number>2;
char *tmp;
$<device>$->path_a = strtol(strdup($<string>3), &tmp, 16);
if (*tmp == '.') {
tmp++;
$<device>$->path_b = strtol(tmp, NULL, 16);
}
char *name = malloc(10);
sprintf(name, "_dev%d", $<device>$->id);
$<device>$->name = name;
$<device>$->name_underscore = name; // shouldn't be necessary, but avoid 0-ptr
$<device>$->type = device;
$<device>$->enabled = $<number>4;
$<device>$->chip = $<device>$->parent->chip;
if (cur_parent->latestchild) {
cur_parent->latestchild->next_sibling = $<device>$;
cur_parent->latestchild->sibling = $<device>$;
}
cur_parent->latestchild = $<device>$;
if (!cur_parent->children)
cur_parent->children = $<device>$;
lastdev->nextdev = $<device>$;
lastdev = $<device>$;
if ($<number>2 == PCI) {
$<device>$->path = ".type=DEVICE_PATH_PCI,{.pci={ .devfn = PCI_DEVFN(0x%x,%d)}}";
}
if ($<number>2 == PNP) {
$<device>$->path = ".type=DEVICE_PATH_PNP,{.pnp={ .port = 0x%x, .device = 0x%x }}";
}
if ($<number>2 == I2C) {
$<device>$->path = ".type=DEVICE_PATH_I2C,{.i2c={ .device = 0x%x }}";
}
if ($<number>2 == APIC) {
$<device>$->path = ".type=DEVICE_PATH_APIC,{.apic={ .apic_id = 0x%x }}";
}
if ($<number>2 == APIC_CLUSTER) {
$<device>$->path = ".type=DEVICE_PATH_APIC_CLUSTER,{.apic_cluster={ .cluster = 0x%x }}";
}
if ($<number>2 == PCI_DOMAIN) {
$<device>$->path = ".type=DEVICE_PATH_PCI_DOMAIN,{.pci_domain={ .domain = 0x%x }}";
}
cur_parent = $<device>$; cur_parent = $<device>$;
cur_bus = $<device>$; cur_bus = $<device>$;
} }
devicesorresources END { devicesorresources END {
cur_parent = $<device>5->parent; cur_parent = $<device>5->parent;
cur_bus = $<device>5->bus; cur_bus = $<device>5->bus;
fold_in($<device>5); fold_in($<device>5);
alias_siblings($<device>5->children);
struct device *d = $<device>5->children;
while (d) {
int link = 0;
struct device *cmp = d->next_sibling;
while (cmp && (cmp->bus == d->bus) && (cmp->path_a == d->path_a) && (cmp->path_b == d->path_b)) {
if (cmp->type==device && !cmp->used) {
if (device_match(d, cmp)) {
d->multidev = 1;
cmp->aliased_name = malloc(12);
sprintf(cmp->aliased_name, "_dev%d", cmp->id);
cmp->id = d->id;
cmp->name = d->name;
cmp->used = 1;
cmp->link = ++link;
}
}
cmp = cmp->next_sibling;
}
d = d->next_sibling;
}
}; };
resource: RESOURCE NUMBER /* == resnum */ EQUALS NUMBER /* == resval */ resource: RESOURCE NUMBER /* == resnum */ EQUALS NUMBER /* == resval */
{ { add_resource($<number>1, strtol($<string>2, NULL, 0), strtol($<string>4, NULL, 0)); } ;
struct resource *r = malloc(sizeof(struct resource));
memset (r, 0, sizeof(struct resource));
r->type = $<number>1;
r->index = strtol($<string>2, NULL, 0);
r->base = strtol($<string>4, NULL, 0);
if (cur_parent->res) {
struct resource *head = cur_parent->res;
while (head->next) head = head->next;
head->next = r;
} else {
cur_parent->res = r;
}
cur_parent->rescnt++;
}
;
registers: REGISTER STRING /* == regname */ EQUALS STRING /* == regval */ registers: REGISTER STRING /* == regname */ EQUALS STRING /* == regval */
{ { add_register($<string>2, $<string>4); } ;
struct reg *r = malloc(sizeof(struct reg));
memset (r, 0, sizeof(struct reg));
r->key = $<string>2;
r->value = $<string>4;
if (cur_parent->reg) {
struct reg *head = cur_parent->reg;
// sorting to be equal to sconfig's behaviour
int sort = strcmp(r->key, head->key);
if (sort == 0) {
printf("ERROR: duplicate 'register' key.\n");
exit(1);
}
if (sort<0) {
r->next = head;
cur_parent->reg = r;
} else {
while ((head->next) && (strcmp(head->next->key, r->key)<0)) head = head->next;
r->next = head->next;
head->next = r;
}
} else {
cur_parent->reg = r;
}
}
;
%% %%
void pass0(FILE *fil, struct device *ptr) {
if ((ptr->type == device) && (ptr->id != 0) && (!ptr->used))
fprintf(fil, "struct device %s;\n", ptr->name);
if ((ptr->type == device) && (ptr->id != 0) && ptr->used)
fprintf(fil, "struct device %s;\n", ptr->aliased_name);
}
void pass1(FILE *fil, struct device *ptr) {
if (!ptr->used && (ptr->type == device)) {
fprintf(fil, "struct device %s = {\n", ptr->name);
fprintf(fil, "\t.ops = %s,\n", (ptr->ops)?(ptr->ops):"0");
fprintf(fil, "\t.bus = &%s.link[%d],\n", ptr->bus->name, ptr->bus->link);
fprintf(fil, "\t.path = {");
fprintf(fil, ptr->path, ptr->path_a, ptr->path_b);
fprintf(fil, "},\n");
fprintf(fil, "\t.enabled = %d,\n", ptr->enabled);
fprintf(fil, "\t.on_mainboard = 1,\n");
if (ptr->rescnt > 0) {
fprintf(fil, "\t.resources = %d,\n", ptr->rescnt);
fprintf(fil, "\t.resource = {\n");
struct resource *r = ptr->res;
while (r) {
fprintf(fil, "\t\t{ .flags=IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_");
if (r->type == IRQ) fprintf(fil, "IRQ");
if (r->type == DRQ) fprintf(fil, "DRQ");
if (r->type == IO) fprintf(fil, "IO");
fprintf(fil, ", .index=0x%x, .base=0x%x},\n", r->index, r->base);
r = r->next;
}
fprintf(fil, "\t },\n");
}
int link = 0;
fprintf(fil, "\t.link = {\n");
if (ptr->multidev) {
struct device *d = ptr;
while (d) {
if (device_match(d, ptr)) {
fprintf(fil, "\t\t[%d] = {\n", d->link);
fprintf(fil, "\t\t\t.link = %d,\n", d->link);
fprintf(fil, "\t\t\t.dev = &%s,\n", d->name);
if (d->children)
fprintf(fil, "\t\t\t.children = &%s,\n", d->children->name);
fprintf(fil, "\t\t},\n");
link++;
}
d = d->next_sibling;
}
} else {
if (ptr->children) {
fprintf(fil, "\t\t[0] = {\n");
fprintf(fil, "\t\t\t.link = 0,\n");
fprintf(fil, "\t\t\t.dev = &%s,\n", ptr->name);
fprintf(fil, "\t\t\t.children = &%s,\n", ptr->children->name);
fprintf(fil, "\t\t},\n");
link++;
}
}
fprintf(fil, "\t},\n");
fprintf(fil, "\t.links = %d,\n", link);
if (ptr->sibling)
fprintf(fil, "\t.sibling = &%s,\n", ptr->sibling->name);
if (ptr->chip->chiph_exists) {
fprintf(fil, "\t.chip_ops = &%s_ops,\n", ptr->chip->name_underscore);
fprintf(fil, "\t.chip_info = &%s_info_%d,\n", ptr->chip->name_underscore, ptr->chip->id);
}
if (ptr->nextdev)
fprintf(fil, "\t.next=&%s\n", ptr->nextdev->name);
fprintf(fil, "};\n");
}
if ((ptr->type == chip) && (ptr->chiph_exists)) {
if (ptr->reg) {
fprintf(fil, "struct %s_config %s_info_%d\t= {\n", ptr->name_underscore, ptr->name_underscore, ptr->id);
struct reg *r = ptr->reg;
while (r) {
fprintf(fil, "\t.%s = %s,\n", r->key, r->value);
r = r->next;
}
fprintf(fil, "};\n\n");
} else {
fprintf(fil, "struct %s_config %s_info_%d;\n", ptr->name_underscore, ptr->name_underscore, ptr->id);
}
}
}
void walk_device_tree(FILE *fil, struct device *ptr, void (*func)(FILE *, struct device*), struct device *chips) {
do {
func(fil, ptr);
ptr = ptr->next_sibling;
} while (ptr);
}
struct device mainboard = {
.name = "mainboard",
.name_underscore = "mainboard",
.id = 0,
.chip = &mainboard,
.type = chip,
.chiph_exists = 1,
.children = &root
};
struct device root = {
.name = "dev_root",
.name_underscore = "dev_root",
.id = 0,
.chip = &mainboard,
.type = device,
.path = " .type = DEVICE_PATH_ROOT ",
.ops = "&default_dev_ops_root",
.parent = &root,
.bus = &root,
.enabled = 1
};
int main(int argc, char** argv) {
if (argc != 3) {
printf("usage: sconfig vendor/mainboard outputdir\n");
return 1;
}
char *mainboard=argv[1];
char *outputdir=argv[2];
char *devtree=malloc(strlen(mainboard)+30);
char *outputc=malloc(strlen(outputdir)+10);
sprintf(devtree, "src/mainboard/%s/devicetree.cb", mainboard);
sprintf(outputc, "%s/static.c", outputdir);
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");
yyrestart(filec);
FILE *staticc = fopen(outputc, "w");
cur_bus = cur_parent = lastdev = head = &root;
yyparse();
fclose(filec);
if ((head->type == chip) && (!head->chiph_exists)) {
struct device *tmp = head;
head = &root;
while (head->next != tmp) head = head->next;
}
fprintf(staticc, "#include <device/device.h>\n");
fprintf(staticc, "#include <device/pci.h>\n");
struct header *h = &headers;
while (h->next) {
h = h->next;
fprintf(staticc, "#include \"%s/chip.h\"\n", h->name);
}
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_p = &%s.next;\n", lastdev->name);
walk_device_tree(staticc, &root, pass1, NULL);
fclose(staticc);
return 0;
}