diff options
Diffstat (limited to 'cfe/cfe/hosttools')
-rw-r--r-- | cfe/cfe/hosttools/Makefile | 12 | ||||
-rw-r--r-- | cfe/cfe/hosttools/README | 49 | ||||
-rw-r--r-- | cfe/cfe/hosttools/installboot.c | 352 | ||||
-rw-r--r-- | cfe/cfe/hosttools/makereg.c | 481 | ||||
-rw-r--r-- | cfe/cfe/hosttools/memconfig.c | 654 | ||||
-rw-r--r-- | cfe/cfe/hosttools/mkbootimage.c | 314 | ||||
-rw-r--r-- | cfe/cfe/hosttools/mkflashimage.c | 347 | ||||
-rw-r--r-- | cfe/cfe/hosttools/mkpcidb.c | 157 |
8 files changed, 2366 insertions, 0 deletions
diff --git a/cfe/cfe/hosttools/Makefile b/cfe/cfe/hosttools/Makefile new file mode 100644 index 0000000..2f04639 --- /dev/null +++ b/cfe/cfe/hosttools/Makefile @@ -0,0 +1,12 @@ + +CC = gcc +CFLAGS = -I ../include + +all : mkbootimage installboot + +mkbootimage : mkbootimage.c + $(CC) $(CFLAGS) -o mkbootimage mkbootimage.c + +installboot : installboot.c + $(CC) $(CFLAGS) -o installboot installboot.c + diff --git a/cfe/cfe/hosttools/README b/cfe/cfe/hosttools/README new file mode 100644 index 0000000..7976c6d --- /dev/null +++ b/cfe/cfe/hosttools/README @@ -0,0 +1,49 @@ + +This directory contains some "host tools" that may be useful for +porting CFE. + +MKBOOTIMAGE +----------- + +The 'mkbootimage' program is used to attach a CFE boot block to +an image file. Boot blocks are used on block-structured devices +such as disks and CD-ROM. + +The boot block contains information to help CFE locate the boot +loader program and verify its validity. To create boot file, +link your boot loader to be executable within CFE's boot +environment (it should be a binary file, not an ELF file). + +Convert the file to a boot block using: + + mkbootimage [-EB] [-EL] myfile.elf myfile.boot + +Supply the -EB or -EL switch to configure the target endianness, +since the values in the boot block are endian-specific. + + +INSTALLBOOT +----------- + +Once you have a boot file, the 'installboot' program can +insert the boot file into a simulated disk file (such as the +file that you can use with the IDE emulation in the +BCM12500's functional simulator). The 'installboot' program +installs your boot file into a disk image file starting at +the first sector, preserving the beginning part of the boot +sector where the the boot block lives. + +Install the boot block using: + + installboot myfile.boot my_disk_image.dsk + +Where the "my_disk_image.dsk" is the simulated disk file for +the functional simulator. + +installboot could probably be ported to the target OS to +install boot blocks on raw disk devices. + + + + + diff --git a/cfe/cfe/hosttools/installboot.c b/cfe/cfe/hosttools/installboot.c new file mode 100644 index 0000000..2f61415 --- /dev/null +++ b/cfe/cfe/hosttools/installboot.c @@ -0,0 +1,352 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Boot program installer File: installboot.c + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + * This program converts a binary file (bootstrap program) + * into a boot block by prepending the boot block sector + * to the program. It generates the appropriate + * boot block checksums and such. The resulting file may + * be used by installboot (for example) to put into a disk + * image for the simulator. + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#include <sys/types.h> +#include <sys/stat.h> + +typedef unsigned long long uint64_t; +typedef unsigned long uint32_t; + +#include "cfe_bootblock.h" +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define roundup(x,align) (((x)+(align)-1)&~((align)-1)) +#define howmany(x,align) (((x)+(align)-1)/(align)) + +static int verbose = 0; +static int big_endian = 1; +static int swapflg = 1; +static unsigned long bootcode_offset = 2; +static unsigned long bootsect_offset = 1; + +static void usage(void) +{ + fprintf(stderr,"usage: installboot [-bootsect <sector offset>] [-bootcode <sector offset>]\n" + " [-v] [-EB] [-EL] bootloaderfile.bin devicefile\n\n"); + fprintf(stderr,"This program installs a boot block onto a disk. Typically, installboot\n" + "is used to install sibyl or other OS bootloaders. The binary you install\n" + "should be a raw program (not ELF) located to run in CFE's boot area\n" + "at address 0x2000_0000. The devicefile should be the name of the raw device\n" + "such as /dev/hda on Linux.\n\n" + "Care must be taken when choosing the values for -bootsect and -bootcode\n" + "not to interfere with other partitions on your disk. When partitioning,\n" + "it's a good idea to reserve 3 cylinders at the beginning of the disk for\n" + "the boot loader.\n\n" + "-bootsect nn specifies that the boot sector will be placed on sector 'nn'\n" + "-bootcode nn specifies that the boot program itself will be placed\n" + " on sectors starting with 'nn'. The boot sector will point\n" + " to this sector.\n"); + + exit(1); +} + +static void bswap32(uint32_t *ptr) +{ + unsigned char b; + unsigned char *bptr; + + if (swapflg) { + bptr = (unsigned char *) ptr; + b = bptr[0]; bptr[0] = bptr[3]; bptr[3] = b; + b = bptr[1]; bptr[1] = bptr[2]; bptr[2] = b; + } +} + +static void bswap64(uint64_t *ptr) +{ + unsigned char b; + unsigned char *bptr; + + bptr = (unsigned char *) ptr; + + if (swapflg) { + b = bptr[0]; bptr[0] = bptr[7]; bptr[7] = b; + b = bptr[1]; bptr[1] = bptr[6]; bptr[6] = b; + b = bptr[2]; bptr[2] = bptr[5]; bptr[5] = b; + b = bptr[3]; bptr[3] = bptr[4]; bptr[4] = b; + } +} + + +static void bswap_bootblock(struct boot_block *bb) +{ + int idx; + + for (idx = 59; idx <= 63; idx++) { + bswap64(&(bb->bb_data[idx])); + } +} + +static void do_checksum(void *ptr,int length,uint32_t *csptr,int swap) +{ + uint32_t *p; + uint32_t chksum = 0; + uint32_t d; + + p = (uint32_t *) ptr; + + length /= sizeof(uint32_t); + + while (length) { + d = *p; + if (swap) bswap32(&d); + chksum += d; + p++; + length--; + } + + if (swap) bswap32(&chksum); + + *csptr = chksum; +} + + +static void dumpbootblock(struct boot_block *bb) +{ + int idx; + + fprintf(stderr,"Magic Number: %016llX\n", + bb->bb_magic); + fprintf(stderr,"Boot code offset: %llu\n", + (unsigned long long)bb->bb_secstart); + fprintf(stderr,"Boot code size: %u\n", + (uint32_t) (bb->bb_secsize & BOOT_SECSIZE_MASK)); + fprintf(stderr,"Header checksum: %08X\n", + (uint32_t) (bb->bb_hdrinfo & BOOT_HDR_CHECKSUM_MASK)); + fprintf(stderr,"Header version: %d\n", + (uint32_t) ((bb->bb_hdrinfo & BOOT_HDR_VER_MASK) >> BOOT_HDR_VER_SHIFT)); + fprintf(stderr,"Data checksum: %08X\n", + (uint32_t) ((bb->bb_secsize & BOOT_DATA_CHECKSUM_MASK) >> BOOT_DATA_CHECKSUM_SHIFT)); + fprintf(stderr,"Architecture info: %08X\n", + (uint32_t) (bb->bb_archinfo & BOOT_ARCHINFO_MASK)); + fprintf(stderr,"\n"); + + for (idx = 59; idx <= 63; idx++) { + fprintf(stderr,"Word %d = %016llX\n",idx,bb->bb_data[idx]); + } +} + +static int host_is_little(void) +{ + unsigned long var = 1; + unsigned char *pvar = (unsigned char *) &var; + + return (*pvar == 1); +} + +int main(int argc, char *argv[]) +{ + int fh; + long bootsize; + long bootbufsize; + unsigned char *bootcode; + struct boot_block bootblock; + uint32_t datacsum,hdrcsum; + int host_le; + + while ((argc > 1) && (argv[1][0] == '-')) { + if (strcmp(argv[1],"-v") == 0) { + verbose = 1; + } + else if (strcmp(argv[1],"-EB") == 0) { + big_endian = 1; + } + else if (strcmp(argv[1],"-EL") == 0) { + big_endian = 0; + } + else if (strcmp(argv[1],"-bootsect") == 0) { + char *tmp_ptr; + argv++; + argc--; + if (argc == 1) { + fprintf(stderr,"-bootsect requires an argument\n"); + exit(1); + } + bootsect_offset = strtoul(argv[1], &tmp_ptr, 0); + bootcode_offset = bootsect_offset + 1; /* default if -bootcode not specified */ + if (*tmp_ptr) { + fprintf(stderr,"Unable to parse %s as a sector offset\n", argv[1]); + exit(1); + } + } + else if (strcmp(argv[1],"-bootcode") == 0) { + char *tmp_ptr; + argv++; + argc--; + if (argc == 1) { + fprintf(stderr,"-bootcode requires an argument\n"); + exit(1); + } + bootcode_offset = strtoul(argv[1], &tmp_ptr, 0); + if (*tmp_ptr) { + fprintf(stderr,"Unable to parse %s as a sector offset\n", argv[1]); + exit(1); + } + } + else { + fprintf(stderr,"Invalid switch: %s\n",argv[1]); + exit(1); + } + argv++; + argc--; + } + + /* + * We need to swap things around if the host and + * target are different endianness + */ + + swapflg = 0; + host_le = host_is_little(); + + if (big_endian && host_is_little()) swapflg = 1; + if ((big_endian == 0) && !(host_is_little())) swapflg = 1; + + fprintf(stderr,"Host is %s-endian.\n",host_le ? "little" : "big"); + fprintf(stderr,"Target is %s-endian.\n",big_endian ? "big" : "little"); + + if (argc != 3) { + usage(); + } + + /* + * Read in the boot file + */ + + fh = open(argv[1],O_RDONLY); + if (fh < 0) { + perror(argv[1]); + } + + bootsize = lseek(fh,0L,SEEK_END); + lseek(fh,0L,SEEK_SET); + + bootbufsize = roundup(bootsize,BOOT_BLOCK_BLOCKSIZE); + + bootcode = malloc(bootbufsize); + if (bootcode == NULL) { + perror("malloc"); + exit(1); + } + memset(bootcode,0,bootbufsize); + if (read(fh,bootcode,bootsize) != bootsize) { + perror("read"); + exit(1); + } + + close(fh); + + /* + * Construct the boot block + */ + + + /* Checksum the boot code */ + do_checksum(bootcode,bootbufsize,&datacsum,1); + bswap32(&datacsum); + + + /* fill in the boot block fields, and checksum the boot block */ + bootblock.bb_magic = BOOT_MAGIC_NUMBER; + bootblock.bb_hdrinfo = (((uint64_t) BOOT_HDR_VERSION) << BOOT_HDR_VER_SHIFT); + bootblock.bb_secstart = (bootcode_offset * 512); + bootblock.bb_secsize = ((uint64_t) bootbufsize) | + (((uint64_t) datacsum) << BOOT_DATA_CHECKSUM_SHIFT); + bootblock.bb_archinfo = 0; /* XXX */ + + do_checksum(&(bootblock.bb_magic),BOOT_BLOCK_SIZE,&hdrcsum,0); + bootblock.bb_hdrinfo |= (uint64_t) hdrcsum; + + if (verbose) dumpbootblock(&bootblock); + + bswap_bootblock(&bootblock); + + /* + * Now write the output file + */ + + fh = open(argv[2],O_RDWR|O_CREAT,S_IREAD|S_IWRITE); + if (fh < 0) { + perror(argv[2]); + exit(1); + } + + fprintf(stderr,"Installing boot block\n"); + if (lseek(fh, bootsect_offset * 512, SEEK_SET) != (bootsect_offset * 512)) { + perror(argv[2]); + exit(1); + } + if (write(fh,&bootblock,sizeof(bootblock)) != sizeof(bootblock)) { + perror(argv[2]); + exit(1); + } + fprintf(stderr,"Installing bootstrap program\n"); + if (lseek(fh, bootcode_offset * 512, SEEK_SET) != (bootcode_offset * 512)) { + perror(argv[2]); + exit(1); + } + if (write(fh,bootcode,bootbufsize) != bootbufsize) { + perror(argv[2]); + exit(1); + } + + close(fh); + + fprintf(stderr,"Done. %s installed on %s\n",argv[1],argv[2]); + + exit(0); + + +} + diff --git a/cfe/cfe/hosttools/makereg.c b/cfe/cfe/hosttools/makereg.c new file mode 100644 index 0000000..0ff53e1 --- /dev/null +++ b/cfe/cfe/hosttools/makereg.c @@ -0,0 +1,481 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Register Table Generator File: makereg.c + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + * Warning: don't eat your lunch before reading this program. + * It's nasty! + * + * This program generates tables of SOC registers and values + * that are easy for us to display. + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#include <stdio.h> +#include <string.h> +#include <malloc.h> +#include <stdlib.h> + +#if defined(_MSC_VER) || defined(__CYGWIN__) +#define TEXTMODE "t" +#else +#define TEXTMODE "" +#endif + +typedef struct Cons { + char *str; + int num; +} CONS; + +typedef struct RegInfo { + unsigned long reg_mask; + char *reg_agent; + int reg_agentidx; + char *reg_addr; + char *reg_inst; + char *reg_subinst; + char *reg_printfunc; + char *reg_description; +} REGINFO; + +typedef struct ConstInfo { + char *name; + unsigned int value; +} CONSTINFO; + +#define MAXCONST 64 +CONSTINFO constants[MAXCONST]; +int constcnt = 0; + +#define MAXREGS 2000 +REGINFO allregs[MAXREGS]; +int regcnt = 0; + +int maskcnt = 0; + +#define MAXAGENTS 32 +char *agentnames[MAXAGENTS]; +int agentcnt; + +#define CMD_AGENT 1 +#define CMD_ENDAGENT 2 + +CONS commands[] = { + {"!agent",CMD_AGENT}, + {"!endagent",CMD_ENDAGENT}, + {NULL,0}}; + + +int assoc(CONS *list,char *str) +{ + while (list->str) { + if (strcmp(list->str,str) == 0) return list->num; + list++; + } + + return -1; +} + +char *gettoken(char **ptr) +{ + char *p = *ptr; + char *ret; + + /* skip white space */ + + while (*p && isspace(*p)) p++; + ret = p; + + /* check for end of string */ + + if (!*p) { + *ptr = p; + return NULL; + } + + /* skip non-whitespace */ + + while (*p) { + if (isspace(*p)) break; + + /* do quoted strings */ + + if (*p == '"') { + p++; + ret = p; + while (*p && (*p != '"')) p++; + if (*p == '"') *p = '\0'; + } + + p++; + + } + + if (*p) { + *p++ = '\0'; + } + *ptr = p; + + return ret; +} + +static int readline(FILE *str,char *dest,int destlen) +{ + char *x; + + for (;;) { + if (!fgets(dest,destlen,str)) return -1; + if (x = strchr(dest,'\n')) *x = '\0'; + if (dest[0] == '\0') continue; + if (dest[0] == ';') continue; + break; + } + + return 0; +} + + +static void fatal(char *str,char *val) +{ + fprintf(stderr,"fatal error: %s %s\n",str,val ? val : ""); + exit(1); +} + +static unsigned int newmask(void) +{ + int res; + + res = maskcnt; + + if (maskcnt == 32) { + fatal("Out of mask bits",NULL); + } + + maskcnt++; + + return 1<<res; +} + +static void addconst(char *name,unsigned int val) +{ + if (constcnt == MAXCONST) { + fatal("Out of constant space",NULL); + } + + constants[constcnt].name = strdup(name); + constants[constcnt].value = val; + + constcnt++; +} + +static void addreg( + char *agentname, + int agentidx, + unsigned long mask, + char *addr, + char *inst, + char *subinst, + char *printfunc, + char *description) +{ + allregs[regcnt].reg_mask = mask; + allregs[regcnt].reg_addr = strdup(addr); + allregs[regcnt].reg_agent = strdup(agentname); + allregs[regcnt].reg_agentidx = agentidx; + allregs[regcnt].reg_inst = strdup(inst); + allregs[regcnt].reg_subinst = strdup(subinst); + allregs[regcnt].reg_printfunc = strdup(printfunc); + allregs[regcnt].reg_description = strdup(description); + regcnt++; +} + + +static void macroexpand(char *instr,char *exp,char *outstr) +{ + while (*instr) { + if (*instr == '$') { + strcpy(outstr,exp); + outstr += strlen(outstr); + instr++; + } + else { + *outstr++ = *instr++; + } + } + + *outstr = '\0'; +} + + +static void doagentcmd(FILE *str,char *line) +{ + char *agentname; + char *instances; + char *inst; + char *ptr; + char regline[500]; + char cumlname[100]; + REGINFO regs[100]; + char temp[20]; + int rmax = 0; + int idx; + unsigned int cumlmask; + int agentidx; + + agentname = gettoken(&line); + instances = gettoken(&line); + if (!instances) { + strcpy(temp,"*"); + instances = temp; + } + + fprintf(stderr,"Agent %s Instances %s\n",agentname,instances); + + if (agentcnt == MAXAGENTS) { + fatal("Out of agent slots\n",NULL); + } + + agentnames[agentcnt] = strdup(agentname); + agentidx = agentcnt; + agentcnt++; + + regline[0] = '\0'; + + while ((readline(str,regline,sizeof(regline)) >= 0) && (rmax < 100)) { + char *atext,*subinst,*pfunc,*descr; + + if (regline[0] == '!') break; + + ptr = regline; + atext = gettoken(&ptr); + subinst = gettoken(&ptr); + pfunc = gettoken(&ptr); + descr = gettoken(&ptr); + + if (!descr) { + fatal("Missing fields for ",atext); + } + + regs[rmax].reg_addr = strdup(atext); + regs[rmax].reg_subinst = strdup(subinst); + regs[rmax].reg_printfunc = strdup(pfunc); + regs[rmax].reg_description = strdup(descr); + regs[rmax].reg_mask = 0; + rmax++; + } + + if (rmax == 100) fatal("Too many registers in section ",agentname); + + inst = strtok(instances,","); + + cumlmask = 0; + while (inst) { + char defname[100]; + unsigned int curmask; + + sprintf(defname,"SOC_AGENT_%s%s", + agentname,inst[0] == '*' ? "" : inst); + + curmask = newmask(); + cumlmask |= curmask; + + addconst(defname,curmask); + + for (idx = 0; idx < rmax; idx++) { + char descr[100]; + char atext[200]; + + macroexpand(regs[idx].reg_addr,inst,atext); +#if 0 + strcpy(descr,agentname); + if (inst[0] != '*') { + strcat(descr,inst); + } + strcat(descr," "); + if (regs[idx].reg_subinst[0] != '*') { + strcat(descr,regs[idx].reg_subinst); + strcat(descr," "); + } + strcat(descr,regs[idx].reg_description); +#else + strcpy(descr,regs[idx].reg_description); +#endif + + addreg(agentname, + agentidx, + curmask, + atext, + inst, + regs[idx].reg_subinst, + regs[idx].reg_printfunc, + descr); + } + inst = strtok(NULL,","); + } + + if (instances[0] != '*') { + sprintf(cumlname,"SOC_AGENT_%s",agentname); + addconst(cumlname,cumlmask); + } +} + +static void docommand(FILE *str,char *line) +{ + char *cmd; + + cmd = gettoken(&line); + if (!cmd) return; + + switch (assoc(commands,cmd)) { + case CMD_AGENT: + doagentcmd(str,line); + break; + default: + fatal("Invalid command",cmd); + break; + } + +} + +static int ingestfile(FILE *str) +{ + char line[500]; + + while (readline(str,line,sizeof(line)) >= 0) { + if (line[0] == '!') { + docommand(str,line); + } + else { + fatal("Command string required before register data",NULL); + } + } +} + + +void saveincfile(char *fname) +{ + FILE *str; + int idx; + + str = fopen(fname,"w" TEXTMODE); + if (!str) { + perror(fname); + exit(1); + } + + fprintf(str,"\n\n"); + + fprintf(str,"#ifndef %s\n",constants[0].name); + for (idx = 0; idx < constcnt; idx++) { + fprintf(str,"#define %s 0x%08X\n",constants[idx].name, + constants[idx].value); + } + fprintf(str,"#endif\n"); + + fprintf(str,"\n\n"); + + fprintf(str,"#ifdef _CFE_\n"); + fprintf(str,"#ifdef __ASSEMBLER__\n"); + fprintf(str,"\t.globl socstatetable\n"); + fprintf(str,"socstatetable:\n"); + for (idx = 0; idx < regcnt; idx++) { + fprintf(str,"\t\t.word 0x%08X,%s\n", + allregs[idx].reg_mask,allregs[idx].reg_addr); + } + fprintf(str,"\t\t.word 0,0\n"); + fprintf(str,"#endif\n"); + + fprintf(str,"\n\n"); + fprintf(str,"#ifndef __ASSEMBLER__\n"); + + /* Addr Agent Inst Subinst Mask Printfunc Descr */ + + fprintf(str,"char *socagents[] = {\n"); + for (idx = 0; idx < agentcnt; idx++) { + fprintf(str,"\t\"%s\",\n",agentnames[idx]); + } + fprintf(str,"\tNULL};\n\n"); + + fprintf(str,"const socreg_t socregs[] = {\n"); + for (idx = 0; idx < regcnt; idx++) { + fprintf(str," {%s,%d,\"%s\",\"%s\",\n 0x%08X,%s,\"%s\"},\n", + allregs[idx].reg_addr, + allregs[idx].reg_agentidx, + allregs[idx].reg_inst, + allregs[idx].reg_subinst, + allregs[idx].reg_mask, + allregs[idx].reg_printfunc, + allregs[idx].reg_description); + } + fprintf(str," {0,0,NULL,NULL,0,NULL,NULL}};\n\n"); + + fprintf(str,"#endif\n"); + fprintf(str,"#endif\n"); + fclose(str); +} + +int main(int argc,char *argv[]) +{ + FILE *str; + int idx; + + if (argc != 3) { + fprintf(stderr,"usage: makereg inputfile outputfile\n"); + exit(1); + } + + str = fopen(argv[1],"r" TEXTMODE); + + if (!str) { + perror(argv[1]); + exit(1); + } + + ingestfile(str); + + fclose(str); + + fprintf(stderr,"Total registers: %d\n",regcnt); + + saveincfile(argv[2]); + + exit(0); + return 0; +} diff --git a/cfe/cfe/hosttools/memconfig.c b/cfe/cfe/hosttools/memconfig.c new file mode 100644 index 0000000..3d84b05 --- /dev/null +++ b/cfe/cfe/hosttools/memconfig.c @@ -0,0 +1,654 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Memory Config Utility File: memconfig.c + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + * This host tool lets you enter DRAM parameters and run CFE's + * standard memory configuration to calculate the relevant timing + * parameters. It's a good way to see what CFE would have done, + * to find bogus timing calculations. + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#include <stdio.h> +#include <string.h> + +/* ********************************************************************* + * Basic types + ********************************************************************* */ + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; +typedef unsigned long long uint64_t; + +/* ********************************************************************* + * SB1250 stuff + ********************************************************************* */ + +#include "sb1250_defs.h" +#include "sb1250_mc.h" +#include "sb1250_draminit.h" +#include "sb1250_regs.h" +#include "sb1250_scd.h" + +/* ********************************************************************* + * BCD macros + ********************************************************************* */ + +#define DECTO10THS(x) ((((x) >> 4)*10)+((x) & 0x0F)) + +/* ********************************************************************* + * Global defaults + ********************************************************************* */ + +#define MIN_tMEMCLK DRT10(8,0) +#define tROUNDTRIP DRT10(2,5) + +/* ********************************************************************* + * Types + ********************************************************************* */ + +typedef struct encvalue_s { + char *name; + uint8_t val; +} encvalue_t; + +typedef struct spdbyte_s { + char *name; + uint8_t *data; + int decimal; + encvalue_t *values; + char *units; + char *description; + char *deflt; +} spdbyte_t; + +#define SPD_DEC_BCD 1 +#define SPD_DEC_QTR 2 +#define SPD_ENCODED 3 +#define SPD_ENCODED2 4 + +/* ********************************************************************* + * Globals + ********************************************************************* */ + + +uint8_t spd[64] = {0}; /* SPD data */ +uint8_t mintmemclk = MIN_tMEMCLK; /* Default value: 8.0ns */ +uint8_t roundtrip = tROUNDTRIP; /* Default value: 2.5ns */ +uint8_t dramtype = JEDEC; /* Regular DDR SDRAMs */ +uint8_t plldiv = 10; /* 500 MHz using 100Mhz refclk */ +uint8_t refclk = 100; /* 100Mhz reference clock */ +uint8_t portintlv = 0; /* no port interleaving */ + +uint8_t addrskew = 0xF; +uint8_t dqoskew = 0x8; +uint8_t dqiskew = 0x8; +uint8_t addrdrive = 0xF; +uint8_t datadrive = 0xF; +uint8_t clkdrive = 0; + +uint64_t mc0_mclkcfg; /* Value programmed by draminit */ +uint64_t mc0_timing1; /* Value programmed by draminit */ +uint64_t smbus0_start = 0; /* Rememberd SMBus register value */ +uint64_t smbus0_cmd = 0; /* Rememberd SMBus register value */ + +extern int sb1250_refclk; /* from draminit - reference clock */ +extern int dram_cas_latency; /* from draminit - calc'd cas latency */ +extern int dram_tMemClk; /* from draminit - calc'd tMemClk */ + +draminittab_t inittab[16]; /* our init tab */ + +int debug = 0; + +/* ********************************************************************* + * Parameter and value tables + ********************************************************************* */ + +encvalue_t caslatencies[] = { + {"3.5",JEDEC_CASLAT_35}, + {"3.0",JEDEC_CASLAT_30}, + {"2.5",JEDEC_CASLAT_25}, + {"2.0",JEDEC_CASLAT_20}, + {"1.5",JEDEC_CASLAT_15}, + {"1.0",JEDEC_CASLAT_10}, + {NULL,0}}; + +encvalue_t refreshrates[] = { + {"64",JEDEC_RFSH_64khz}, + {"256",JEDEC_RFSH_256khz}, + {"128",JEDEC_RFSH_128khz}, + {"32",JEDEC_RFSH_32khz}, + {"16",JEDEC_RFSH_16khz}, + {"8",JEDEC_RFSH_8khz}, + {NULL,0}}; + +encvalue_t modattribs[] = { + {"none",0}, + {"reg",JEDEC_ATTRIB_REG}, + {"diffclk",0x20}, + {NULL,0}}; + +encvalue_t dramtypes[] = { + {"jedec",JEDEC}, + {"fcram",FCRAM}, + {"sgram",SGRAM}, + {NULL,0}}; + +spdbyte_t spdfields[] = { + {"mintmemclk",&mintmemclk,SPD_DEC_BCD,NULL,"ns","Minimum value for tMEMCLK","8.0"}, + {"roundtrip", &roundtrip, SPD_DEC_BCD,NULL,"ns","Round trip time from CLK to returned DQS","2.5"}, + {"plldiv", &plldiv, 0,NULL,"","PLL Ratio (System Config Register)","10"}, + {"refclk", &refclk, 0,NULL,"Mhz","Reference clock, usually 100Mhz","100"}, +// {"portintlv", &portintlv, 0,NULL,"","Port interleave (1=on)","0"}, + {"memtype", &dramtype, SPD_ENCODED,dramtypes,"","Memory type (jedec, fcram, sgram)","jedec"}, + {"rows", &spd[JEDEC_SPD_ROWS],0,NULL,"","[3 ] Number of row bits","13"}, + {"cols", &spd[JEDEC_SPD_COLS],0,NULL,"","[4 ] Number of column bits","9"}, + {"banks", &spd[JEDEC_SPD_BANKS],0,NULL,"","[17] Number of banks","4"}, + {"tCK25", &spd[JEDEC_SPD_tCK25],SPD_DEC_BCD,NULL,"ns","[9 ] tCK value for CAS Latency 2.5","7.5"}, + {"tCK20", &spd[JEDEC_SPD_tCK20],SPD_DEC_BCD,NULL,"ns","[23] tCK value for CAS Latency 2.0","0"}, + {"tCK10", &spd[JEDEC_SPD_tCK10],SPD_DEC_BCD,NULL,"ns","[25] tCK value for CAS Latency 1.0","0"}, + {"rfsh", &spd[JEDEC_SPD_RFSH],SPD_ENCODED,refreshrates,"","[12] Refresh rate (KHz)","8"}, + {"caslat", &spd[JEDEC_SPD_CASLATENCIES],SPD_ENCODED2,caslatencies,"","[18] CAS Latencies supported","2.5"}, + {"attrib", &spd[JEDEC_SPD_ATTRIBUTES],SPD_ENCODED,modattribs,"","[21] Module attributes","none"}, + {"tRAS", &spd[JEDEC_SPD_tRAS],0,NULL,"ns","[30]","45"}, + {"tRP", &spd[JEDEC_SPD_tRP],SPD_DEC_QTR,NULL,"ns","[27]","20.0"}, + {"tRRD", &spd[JEDEC_SPD_tRRD],SPD_DEC_QTR,NULL,"ns","[28]","15.0"}, + {"tRCD", &spd[JEDEC_SPD_tRCD],SPD_DEC_QTR,NULL,"ns","[29]","20.0"}, + {"tRFC", &spd[JEDEC_SPD_tRFC],0,NULL,"ns","[42]","0"}, + {"tRC", &spd[JEDEC_SPD_tRC],0,NULL,"ns","[41]","0"}, + + {"addrskew", &addrskew, 0, NULL, "","Address Skew","0x0F"}, + {"dqoskew", &dqoskew, 0, NULL, "","DQO Skew","0x08"}, + {"dqikew", &dqiskew, 0, NULL, "","DQI Skew","0x08"}, + {"addrdrive", &addrdrive, 0, NULL, "","Address Drive","0x0F"}, + {"datadrive", &datadrive, 0, NULL, "","Data Drive","0x0F"}, + {"clkdrive", &clkdrive, 0, NULL, "","Clock Drive","0"}, + {NULL,0,0,NULL,NULL,NULL,NULL}}; + +char *lookupstr(encvalue_t *ev,uint8_t val) +{ + while (ev->name) { + if (ev->val == val) return ev->name; + ev++; + } + return "unknown"; +} + +uint64_t sbreadcsr(uint64_t reg) +{ + uint64_t val = 0; + + if (debug) printf("READ %08X\n",(uint32_t) reg); + + switch ((uint32_t) reg) { + case A_SCD_SYSTEM_REVISION: + val = V_SYS_PART(0x1250) | V_SYS_WID(0) | V_SYS_REVISION(1) | 0xFF; + break; + case A_SCD_SYSTEM_CFG: + val = V_SYS_PLL_DIV(plldiv); + break; + case A_SMB_STATUS_0: + val = 0; + break; + case A_SMB_CMD_0: + val = smbus0_cmd; + break; + case A_SMB_START_0: + val = smbus0_start; + break; + case A_SMB_DATA_0: + val = spd[smbus0_cmd & 0x3F]; + break; + } + return val; +} + +void sbwritecsr(uint64_t reg,uint64_t val) +{ + if (debug) printf("WRITE %08X %016llX\n",(uint32_t) reg,val); + + switch ((uint32_t) reg) { + case A_MC_REGISTER(0,R_MC_MCLK_CFG): + mc0_mclkcfg = val; + break; + case A_MC_REGISTER(0,R_MC_TIMING1): + mc0_timing1 = val; + break; + case A_SMB_CMD_0: + smbus0_cmd = val; + break; + case A_SMB_START_0: + smbus0_start = val; + break; + } +} + + +int procfield(char *txt) +{ + int num = 0; + int a,b; + spdbyte_t *sf; + encvalue_t *ev; + char *x; + char *tok; + + x = strchr(txt,'='); + if (!x) { + printf("Fields must be specified as 'name=value'\n"); + exit(1); + } + *x++ = '\0'; + + sf = spdfields; + while (sf->name) { + if (strcmp(sf->name,txt) == 0) break; + sf++; + } + + if (sf->name == NULL) { + printf("Invalid field name: %s\n",txt); + return -1; + } + + if (memcmp(x,"0x",2) == 0) { + sscanf(x+2,"%x",&num); + } + else { + if (strchr(x,'.')) { + if (sscanf(x,"%d.%d",&a,&b) != 2) { + printf("%s: invalid number: %s\n",sf->name,x); + return -1; + } + } + else { + a = atoi(x); + b = 0; + } + + switch (sf->decimal) { + case SPD_DEC_BCD: + if ((b < 0) || (b > 9)) { + printf("%s: Invalid BCD number: %s\n",sf->name,x); + return -1; + } + num = (a*16)+b; + break; + case SPD_DEC_QTR: + if ((b != 0) && (b != 25) && (b != 50) && (b != 75)) { + printf("%s: Invalid 2-bit fraction number: %s\n",sf->name,x); + printf("(number after decimal should be 0,25,50,75)\n"); + exit(1); + } + num = (a*4)+(b/25); + break; + case SPD_ENCODED: + ev = sf->values; + while (ev->name) { + if (strcmp(ev->name,x) == 0) break; + ev++; + } + if (!ev->name) { + printf("%s: Invalid value. Valid values are: ",x); + ev = sf->values; + while (ev->name) { printf("%s ",ev->name); ev++; } + printf("\n"); + return -1; + } + num = ev->val; + break; + case SPD_ENCODED2: + tok = strtok(x," ,"); + num = 0; + while (tok) { + ev = sf->values; + while (ev->name) { + if (strcmp(ev->name,tok) == 0) break; + ev++; + } + if (!ev->name) { + printf("%s: Invalid value. Valid values are: ",tok); + ev = sf->values; + while (ev->name) { printf("%s ",ev->name); ev++; } + printf("\n"); + return -1; + } + num |= ev->val; + tok = strtok(NULL," ,"); + } + break; + default: + num = a; + break; + } + } + + *(sf->data) = num; + + return 0; +} + +void interactive(void) +{ + spdbyte_t *sf; + char field[100]; + char ask[100]; + char prompt[100]; + char *x; + + sf = spdfields; + + printf("%-65.65s: Value\n","Parameter"); + printf("%-65.65s: -----\n","-----------------------------------------------------------------"); + + while (sf->name) { + for (;;) { + x = prompt; + x += sprintf(x,"%s (%s", sf->name,sf->description); + if (sf->units && sf->units[0]) { + if (sf->description && sf->description[0]) x += sprintf(x,", "); + x += sprintf(x,"%s",sf->units); + } + x += sprintf(x,"): [%s]", sf->deflt); + printf("%-65.65s: ",prompt); + + fgets(ask,sizeof(ask),stdin); + if ((x = strchr(ask,'\n'))) *x = '\0'; + if (ask[0] == 0) strcpy(ask,sf->deflt); + sprintf(field,"%s=%s",sf->name,ask); + if (procfield(field) < 0) continue; + break; + } + sf++; + } + + printf("\n\n"); +} + +int swcnt = 0; +char *swnames[32]; + +int proc_args(int argc,char *argv[]) +{ + int inidx,outidx; + + outidx = 1; + + for (inidx = 1; inidx < argc; inidx++) { + if (argv[inidx][0] != '-') { + argv[outidx++] = argv[inidx]; + } + else { + swnames[swcnt] = argv[inidx]; + swcnt++; + } + } + + return outidx; +} + +int swisset(char *x) +{ + int idx; + + for (idx = 0; idx < swcnt; idx++) { + if (strcmp(x,swnames[idx]) == 0) return 1; + } + return 0; +} + +void dumpmclkcfg(uint64_t val) +{ + printf("clk_ratio = %d\n",G_MC_CLK_RATIO(val)); + printf("ref_rate = %d\n",G_MC_REF_RATE(val)); + +} + +void dumptiming1(uint64_t val) +{ + printf("w2rIdle = %d\n",(val & M_MC_w2rIDLE_TWOCYCLES) ? 1 : 0); + printf("r2rIdle = %d\n",(val & M_MC_r2rIDLE_TWOCYCLES) ? 1 : 0); + printf("r2wIdle = %d\n",(val & M_MC_r2wIDLE_TWOCYCLES) ? 1 : 0); + printf("tCrD = %d\n",(int)G_MC_tCrD(val)); + printf("tCrDh = %d\n",(val & M_MC_tCrDh) ? 1 : 0); + printf("tFIFO = %d\n",(int)G_MC_tFIFO(val)); + printf("tCwD = %d\n",(int)G_MC_tCwD(val)); + + printf("tRP = %d\n",(int)G_MC_tRP(val)); + printf("tRRD = %d\n",(int)G_MC_tRRD(val)); + printf("tRCD = %d\n",(int)G_MC_tRCD(val)); + + printf("tRFC = %d\n",(int)G_MC_tRFC(val)); + printf("tRCw = %d\n",(int)G_MC_tRCw(val)); + printf("tRCr = %d\n",(int)G_MC_tRCr(val)); + printf("tCwCr = %d\n",(int)G_MC_tCwCr(val)); +} + +int main(int argc,char *argv[]) +{ + spdbyte_t *sf; + uint8_t t; + int idx; + int mclk; + draminittab_t *init; + + spd[JEDEC_SPD_MEMTYPE] = JEDEC_MEMTYPE_DDRSDRAM2; + spd[JEDEC_SPD_ROWS] = 13; + spd[JEDEC_SPD_COLS] = 9; + spd[JEDEC_SPD_BANKS] = 2; + spd[JEDEC_SPD_SIDES] = 1; + spd[JEDEC_SPD_WIDTH] = 72; + + argc = proc_args(argc,argv); + + if ((argc == 1) && !swisset("-i")) { + printf("usage: memconfig name=value name=value ...\n"); + printf("\n"); + printf("Available fields: "); + sf = spdfields; + while (sf->name) { + printf("%s ",sf->name); + sf++; + } + printf("\n"); + exit(1); + } + + if (swisset("-i")) { + interactive(); + } + else { + for (idx = 1; idx < argc; idx++) { + if (procfield(argv[idx]) < 0) exit(1); + } + } + + debug = swisset("-d"); + + printf("-------Memory Parameters---------\n"); + + sf = spdfields; + while (sf->name) { + char buffer[64]; + char *p = buffer; + + t = *(sf->data); + printf("%-10.10s = 0x%02X ",sf->name,t); + switch (sf->decimal) { + case SPD_DEC_BCD: + p += sprintf(p,"(%d.%d)", + t >> 4, t & 0x0F); + break; + case SPD_DEC_QTR: + p += sprintf(p,"(%d.%02d)", + t/4,(t&3)*25); + break; + case SPD_ENCODED: + p += sprintf(p,"(%s)",lookupstr(sf->values,t)); + break; + default: + p += sprintf(p,"(%d)",t); + break; + } + + p += sprintf(p," %s",sf->units); + printf("%-16.16s %s\n",buffer,sf->description); + sf++; + } + + printf("\n"); + + init = &inittab[0]; + memset(inittab,0,sizeof(inittab)); + + init->gbl.gbl_type = MCR_GLOBALS; + init->gbl.gbl_intlv_ch = portintlv; + init++; + + init->cfg.cfg_type = MCR_CHCFG; + init->cfg.cfg_chan = 0; + init->cfg.cfg_mintmemclk = mintmemclk; + init->cfg.cfg_dramtype = dramtype; + init->cfg.cfg_pagepolicy = CASCHECK; + init->cfg.cfg_blksize = BLKSIZE32; + init->cfg.cfg_intlv_cs = NOCSINTLV; + init->cfg.cfg_ecc = 0; + init->cfg.cfg_roundtrip = roundtrip; + init++; + + init->clk.clk_type = MCR_CLKCFG; + init->clk.clk_addrskew = addrskew; + init->clk.clk_dqoskew = dqoskew; + init->clk.clk_dqiskew = dqiskew; + init->clk.clk_addrdrive = addrdrive; + init->clk.clk_datadrive = datadrive; + init->clk.clk_clkdrive = clkdrive; + init++; + + init->geom.geom_type = MCR_GEOM; + init->geom.geom_csel = 0; + init->geom.geom_rows = spd[JEDEC_SPD_ROWS]; + init->geom.geom_cols = spd[JEDEC_SPD_COLS]; + init->geom.geom_banks = spd[JEDEC_SPD_BANKS]; + init++; + +#if 0 + init->tmg.tmg_type = MCR_TIMING; + init->tmg.tmg_tCK = spd[JEDEC_SPD_tCK25]; + init->tmg.tmg_rfsh = spd[JEDEC_SPD_RFSH]; + init->tmg.tmg_caslatency = spd[JEDEC_SPD_CASLATENCIES]; + init->tmg.tmg_attributes = spd[JEDEC_SPD_ATTRIBUTES]; + init->tmg.tmg_tRAS = spd[JEDEC_SPD_tRAS]; + init->tmg.tmg_tRP = spd[JEDEC_SPD_tRP]; + init->tmg.tmg_tRRD = spd[JEDEC_SPD_tRRD]; + init->tmg.tmg_tRCD = spd[JEDEC_SPD_tRCD]; + init->tmg.tmg_tRFC = spd[JEDEC_SPD_tRFC]; + init->tmg.tmg_tRC = spd[JEDEC_SPD_tRC]; + init++; +#else + init->spd.spd_type = MCR_SPD; + init->spd.spd_csel = 0; + init->spd.spd_flags = 0; + init->spd.spd_smbuschan = 0; + init->spd.spd_smbusdev = 0x50; + init++; +#endif + + init->mcr.mcr_type = MCR_EOT; + + + sb1250_refclk = (int) refclk; + + sb1250_dram_init(inittab); + + + printf("-----Memory Timing Register Values-----\n"); + printf("System Clock %dMHz\n",plldiv*refclk/2); + printf("CAS latency %d.%d\n",dram_cas_latency>>1,(dram_cas_latency&1)?5:0); + printf("tMemClk %d.%d ns\n",dram_tMemClk/10,dram_tMemClk%10); + mclk = (plldiv*refclk)*10/2/((int)G_MC_CLK_RATIO(mc0_mclkcfg)); + printf("MCLK Freq %d.%dMHz\n",mclk/10,mclk%10); + printf("\n"); + printf("MC_TIMING1 = %016llX\n",mc0_timing1); + printf("MCLK_CONFIG = %016llX\n",mc0_mclkcfg); + printf("\n"); + + printf("-----Memory Timing Register Fields-----\n"); + dumptiming1(mc0_timing1); + + printf("-----Memory Clock Config Register Fields-----\n"); + dumpmclkcfg(mc0_mclkcfg); + + printf("---Done!---\n"); + + printf("%s ",argv[0]); + sf = spdfields; + while (sf->name) { + char buffer[64]; + char *p = buffer; + + t = *(sf->data); + + p += sprintf(p,"%s=",sf->name); + switch (sf->decimal) { + case SPD_DEC_BCD: + p += sprintf(p,"%d.%d", + t >> 4, t & 0x0F); + break; + case SPD_DEC_QTR: + p += sprintf(p,"%d.%02d", + t/4,(t&3)*25); + break; + case SPD_ENCODED: + default: + p += sprintf(p,"0x%02X",t); + break; + } + + printf("%s ",buffer); + sf++; + } + + printf("\n"); + + return 0; +} diff --git a/cfe/cfe/hosttools/mkbootimage.c b/cfe/cfe/hosttools/mkbootimage.c new file mode 100644 index 0000000..862f8ed --- /dev/null +++ b/cfe/cfe/hosttools/mkbootimage.c @@ -0,0 +1,314 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Boot block generator File: mkbootimage.c + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + * This program converts a binary file (bootstrap program) + * into a boot block by prepending the boot block sector + * to the program. It generates the appropriate + * boot block checksums and such. The resulting file may + * be used by installboot (for example) to put into a disk + * image for the simulator. + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#include <sys/types.h> +#include <sys/stat.h> + +typedef unsigned long long uint64_t; +typedef unsigned long uint32_t; + +#include "cfe_bootblock.h" +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define roundup(x,align) (((x)+(align)-1)&~((align)-1)) +#define howmany(x,align) (((x)+(align)-1)/(align)) + +static int verbose = 0; +static int big_endian = 1; +static int swapflg = 1; +static unsigned long sector_offset = 0; + +static void usage(void) +{ + fprintf(stderr,"usage: mkbootimage [-S <sector offset>] [-v] [-EB] [-EL] inputfile outputfile\n"); + exit(1); +} + +static void bswap32(uint32_t *ptr) +{ + unsigned char b; + unsigned char *bptr; + + if (swapflg) { + bptr = (unsigned char *) ptr; + b = bptr[0]; bptr[0] = bptr[3]; bptr[3] = b; + b = bptr[1]; bptr[1] = bptr[2]; bptr[2] = b; + } +} + +static void bswap64(uint64_t *ptr) +{ + unsigned char b; + unsigned char *bptr; + + bptr = (unsigned char *) ptr; + + if (swapflg) { + b = bptr[0]; bptr[0] = bptr[7]; bptr[7] = b; + b = bptr[1]; bptr[1] = bptr[6]; bptr[6] = b; + b = bptr[2]; bptr[2] = bptr[5]; bptr[5] = b; + b = bptr[3]; bptr[3] = bptr[4]; bptr[4] = b; + } +} + + +static void bswap_bootblock(struct boot_block *bb) +{ + int idx; + + for (idx = 59; idx <= 63; idx++) { + bswap64(&(bb->bb_data[idx])); + } +} + +static void do_checksum(void *ptr,int length,uint32_t *csptr,int swap) +{ + uint32_t *p; + uint32_t chksum = 0; + uint32_t d; + + p = (uint32_t *) ptr; + + length /= sizeof(uint32_t); + + while (length) { + d = *p; + if (swap) bswap32(&d); + chksum += d; + p++; + length--; + } + + if (swap) bswap32(&chksum); + + *csptr = chksum; +} + + +static void dumpbootblock(struct boot_block *bb) +{ + int idx; + + fprintf(stderr,"Magic Number: %016llX\n", + bb->bb_magic); + fprintf(stderr,"Boot code offset: %llu\n", + (unsigned long long)bb->bb_secstart); + fprintf(stderr,"Boot code size: %u\n", + (uint32_t) (bb->bb_secsize & BOOT_SECSIZE_MASK)); + fprintf(stderr,"Header checksum: %08X\n", + (uint32_t) (bb->bb_hdrinfo & BOOT_HDR_CHECKSUM_MASK)); + fprintf(stderr,"Header version: %d\n", + (uint32_t) ((bb->bb_hdrinfo & BOOT_HDR_VER_MASK) >> BOOT_HDR_VER_SHIFT)); + fprintf(stderr,"Data checksum: %08X\n", + (uint32_t) ((bb->bb_secsize & BOOT_DATA_CHECKSUM_MASK) >> BOOT_DATA_CHECKSUM_SHIFT)); + fprintf(stderr,"Architecture info: %08X\n", + (uint32_t) (bb->bb_archinfo & BOOT_ARCHINFO_MASK)); + fprintf(stderr,"\n"); + + for (idx = 59; idx <= 63; idx++) { + fprintf(stderr,"Word %d = %016llX\n",idx,bb->bb_data[idx]); + } +} + +static int host_is_little(void) +{ + unsigned long var = 1; + unsigned char *pvar = (unsigned char *) &var; + + return (*pvar == 1); +} + +int main(int argc, char *argv[]) +{ + int fh; + long bootsize; + long bootbufsize; + unsigned char *bootcode; + struct boot_block bootblock; + uint32_t datacsum,hdrcsum; + int host_le; + + while ((argc > 1) && (argv[1][0] == '-')) { + if (strcmp(argv[1],"-v") == 0) { + verbose = 1; + } + else if (strcmp(argv[1],"-EB") == 0) { + big_endian = 1; + } + else if (strcmp(argv[1],"-EL") == 0) { + big_endian = 0; + } + else if (strcmp(argv[1],"-S") == 0) { + char *tmp_ptr; + argv++; + argc--; + if (argc == 1) { + fprintf(stderr,"-S requires an argument\n"); + exit(1); + } + sector_offset = strtoul(argv[1], &tmp_ptr, 0); + if (*tmp_ptr) { + fprintf(stderr,"Unable to parse %s as a sector offset\n", argv[1]); + exit(1); + } + } + else { + fprintf(stderr,"Invalid switch: %s\n",argv[1]); + exit(1); + } + argv++; + argc--; + } + + /* + * We need to swap things around if the host and + * target are different endianness + */ + + swapflg = 0; + host_le = host_is_little(); + + if (big_endian && host_is_little()) swapflg = 1; + if ((big_endian == 0) && !(host_is_little())) swapflg = 1; + + fprintf(stderr,"Host is %s-endian.\n",host_le ? "little" : "big"); + fprintf(stderr,"Target is %s-endian.\n",big_endian ? "big" : "little"); + + if (argc != 3) { + usage(); + } + + /* + * Read in the boot file + */ + + fh = open(argv[1],O_RDONLY); + if (fh < 0) { + perror(argv[1]); + } + + bootsize = lseek(fh,0L,SEEK_END); + lseek(fh,0L,SEEK_SET); + + bootbufsize = roundup(bootsize,BOOT_BLOCK_BLOCKSIZE); + + bootcode = malloc(bootbufsize); + if (bootcode == NULL) { + perror("malloc"); + exit(1); + } + memset(bootcode,0,bootbufsize); + if (read(fh,bootcode,bootsize) != bootsize) { + perror("read"); + exit(1); + } + + close(fh); + + /* + * Construct the boot block + */ + + + /* Checksum the boot code */ + do_checksum(bootcode,bootbufsize,&datacsum,1); + bswap32(&datacsum); + + + /* fill in the boot block fields, and checksum the boot block */ + bootblock.bb_magic = BOOT_MAGIC_NUMBER; + bootblock.bb_hdrinfo = (((uint64_t) BOOT_HDR_VERSION) << BOOT_HDR_VER_SHIFT); + bootblock.bb_secstart = BOOT_BLOCK_BLOCKSIZE + (sector_offset * 512); + bootblock.bb_secsize = ((uint64_t) bootbufsize) | + (((uint64_t) datacsum) << BOOT_DATA_CHECKSUM_SHIFT); + bootblock.bb_archinfo = 0; /* XXX */ + + do_checksum(&(bootblock.bb_magic),BOOT_BLOCK_SIZE,&hdrcsum,0); + bootblock.bb_hdrinfo |= (uint64_t) hdrcsum; + + if (verbose) dumpbootblock(&bootblock); + + bswap_bootblock(&bootblock); + + /* + * Now write the output file + */ + + fh = open(argv[2],O_RDWR|O_CREAT,S_IREAD|S_IWRITE); + if (fh < 0) { + perror(argv[2]); + exit(1); + } + if (lseek(fh, sector_offset * 512, SEEK_SET) != (sector_offset * 512)) { + perror(argv[2]); + exit(1); + } + if (write(fh,&bootblock,sizeof(bootblock)) != sizeof(bootblock)) { + perror(argv[2]); + exit(1); + } + if (write(fh,bootcode,bootbufsize) != bootbufsize) { + perror(argv[2]); + exit(1); + } + + close(fh); + + fprintf(stderr,"%s -> %s : OK\n",argv[1],argv[2]); + + exit(0); + + +} + diff --git a/cfe/cfe/hosttools/mkflashimage.c b/cfe/cfe/hosttools/mkflashimage.c new file mode 100644 index 0000000..84ec77c --- /dev/null +++ b/cfe/cfe/hosttools/mkflashimage.c @@ -0,0 +1,347 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Flash Image generator File: mkflashimage.c + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + * This program sticks a header on the front of a binary + * file making it suitable for use with the 'flash' command + * in CFE. The header contains the CFE version # and board + * type, a CRC, and other info to help prevent us from + * flashing bad stuff onto a board. + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#include <sys/types.h> +#include <sys/stat.h> + +#ifndef _SYS_INT_TYPES_H +typedef unsigned char uint8_t; +typedef unsigned long long uint64_t; +typedef unsigned long uint32_t; +#endif + +#include "cfe_flashimage.h" +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + + +static int verbose = 0; +static int big_endian = 1; +static int both_endian = 0; +int mlong64 = 0; +char boardname[32]; + +/* + * This is the offset in the flash where the little-endian image goes + * if we're making a bi-endian flash. + */ + +#define CFE_BIENDIAN_LE_OFFSET (1024*1024) + +static void usage(void) +{ + fprintf(stderr,"usage: mkflashimage [-v] [-EB] [-EL] [-64] [-B boardname] [-V v.v.v] binfile outfile\n"); + fprintf(stderr,"\n"); + fprintf(stderr," mkflashimage [-v] -EX [-64] [-B boardname] [-V v.v.v] BE-binfile LE-binfile outfile\n"); + fprintf(stderr," (this variant used for making bi-endian flash files)\n"); + exit(1); +} + + +static int host_is_little(void) +{ + unsigned long var = 1; + unsigned char *pvar = (unsigned char *) &var; + + return (*pvar == 1); +} + +#define CRC32_POLY 0xEDB88320UL /* CRC-32 Poly */ + +static unsigned int +crc32(const unsigned char *databuf, unsigned int datalen) +{ + unsigned int idx, bit, data, crc = 0xFFFFFFFFUL; + + for (idx = 0; idx < datalen; idx++) { + for (data = *databuf++, bit = 0; bit < 8; bit++, data >>= 1) { + crc = (crc >> 1) ^ (((crc ^ data) & 1) ? CRC32_POLY : 0); + } + } + + return crc; +} + + +void stuff_be32(uint8_t *dest,unsigned int src) +{ + *dest++ = (src >> 24) & 0xFF; + *dest++ = (src >> 16) & 0xFF; + *dest++ = (src >> 8) & 0xFF; + *dest++ = (src >> 0) & 0xFF; +} + +int main(int argc, char *argv[]) +{ + int fh; + int flashsize; + unsigned char *flashcode; + cfe_flashimage_t header; + int host_le; + int majver,minver,ecover; + uint32_t crc; + uint32_t flags; + char *outfile; + + majver = minver = ecover = 0; + boardname[0] = 0; + + while ((argc > 1) && (argv[1][0] == '-')) { + if (strcmp(argv[1],"-v") == 0) { + verbose = 1; + } + else if (strcmp(argv[1],"-EX") == 0) { + if (verbose) fprintf(stderr,"[Image file will be marked Bi-Endian]\n"); + both_endian = 1; + } + else if (strcmp(argv[1],"-EB") == 0) { + if (verbose) fprintf(stderr,"[Image file will be marked Big-Endian]\n"); + big_endian = 1; + } + else if (strcmp(argv[1],"-EL") == 0) { + if (verbose) fprintf(stderr,"[Image file will be marked Little-Endian]\n"); + big_endian = 0; + } + else if (strcmp(argv[1],"-64") == 0) { + if (verbose) fprintf(stderr,"[Image file will be marked 64-bit]\n"); + mlong64 = 1; + } + else if (strcmp(argv[1],"-B") == 0) { + argc--; + argv++; + strcpy(boardname,argv[1]); + if (verbose) fprintf(stderr,"[Board name: %s]\n",boardname); + } + else if (strcmp(argv[1],"-V") == 0) { + argc--; + argv++; + sscanf(argv[1],"%d.%d.%d",&majver,&minver,&ecover); + if (verbose) fprintf(stderr,"[Image version: %d.%d.%d]\n",majver,minver,ecover); + } + else { + fprintf(stderr,"Invalid switch: %s\n",argv[1]); + exit(1); + } + argv++; + argc--; + } + + /* + * We need to swap things around if the host and + * target are different endianness + */ + + host_le = host_is_little(); + + if (verbose) { + fprintf(stderr,"Host is %s-endian.\n",host_le ? "little" : "big"); + if (both_endian) { + fprintf(stderr,"Target is bi-endian.\n"); + } + else { + fprintf(stderr,"Target is %s-endian.\n",big_endian ? "big" : "little"); + } + } + + if ((both_endian && (argc != 4)) || (!both_endian && (argc != 3))) { + usage(); + } + + /* + * Read in the boot file(s) + */ + + flags = 0; + + if (both_endian) { + int be_size; + + flags |= (CFE_IMAGE_EB | CFE_IMAGE_EL); + + if (verbose) fprintf(stderr,"Reading: %s\n",argv[2]); + + fh = open(argv[2],O_RDONLY); + if (fh < 0) { + perror(argv[2]); + } + + flashsize = lseek(fh,0L,SEEK_END); + lseek(fh,0L,SEEK_SET); + + flashcode = malloc(flashsize+CFE_BIENDIAN_LE_OFFSET); + if (flashcode == NULL) { + perror("malloc"); + exit(1); + } + memset(flashcode,0xFF,flashsize+CFE_BIENDIAN_LE_OFFSET); + + if (read(fh,flashcode+CFE_BIENDIAN_LE_OFFSET,flashsize) != flashsize) { + perror("read"); + exit(1); + } + + close(fh); + + if (memcmp(flashcode+CFE_BIENDIAN_LE_OFFSET,CFE_IMAGE_SEAL,4) == 0) { + fprintf(stderr,"File '%s' already has an image header.\n",argv[2]); + exit(1); + } + + flashsize += CFE_BIENDIAN_LE_OFFSET; /* actual file size */ + + if (verbose) fprintf(stderr,"Reading: %s\n",argv[1]); + + fh = open(argv[1],O_RDONLY); + if (fh < 0) { + perror(argv[1]); + exit(1); + } + + be_size = lseek(fh,0L,SEEK_END); + lseek(fh,0L,SEEK_SET); + if (be_size > CFE_BIENDIAN_LE_OFFSET) { + fprintf(stderr,"File '%s' will not fit within first %d bytes of flash image\n", + argv[1],CFE_BIENDIAN_LE_OFFSET); + close(fh); + exit(1); + } + + if (read(fh,flashcode,be_size) != be_size) { + perror("read"); + exit(1); + } + + close(fh); + + outfile = argv[3]; + + } + else { + if (big_endian) flags |= CFE_IMAGE_EB; + else flags |= CFE_IMAGE_EL; + + fh = open(argv[1],O_RDONLY); + if (fh < 0) { + perror(argv[1]); + exit(1); + } + + flashsize = lseek(fh,0L,SEEK_END); + lseek(fh,0L,SEEK_SET); + + flashcode = malloc(flashsize); + if (flashcode == NULL) { + perror("malloc"); + exit(1); + } + memset(flashcode,0,flashsize); + if (read(fh,flashcode,flashsize) != flashsize) { + perror("read"); + exit(1); + } + + close(fh); + + if (memcmp(flashcode,CFE_IMAGE_SEAL,4) == 0) { + fprintf(stderr,"File '%s' already has an image header.\n",argv[1]); + exit(1); + } + + outfile = argv[2]; + } + + + /* + * Construct the flash header + */ + + if (mlong64) flags |= CFE_IMAGE_MLONG64; + crc = crc32(flashcode,flashsize); + + memset(&header,0,sizeof(header)); + memcpy(header.seal,CFE_IMAGE_SEAL,sizeof(header.seal)); + stuff_be32(header.flags,flags); + stuff_be32(header.size,flashsize); + stuff_be32(header.crc,crc); + header.majver = majver; + header.minver = minver; + header.ecover = ecover; + header.miscver = 0; + strcpy(header.boardname,boardname); + + /* + * Now write the output file + */ + + fh = open(outfile,O_RDWR|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE|S_IRGRP|S_IWGRP|S_IROTH); + if (fh < 0) { + perror(outfile); + exit(1); + } + if (write(fh,&header,sizeof(header)) != sizeof(header)) { + perror(outfile); + exit(1); + } + if (write(fh,flashcode,flashsize) != flashsize) { + perror(outfile); + exit(1); + } + + fprintf(stderr,"Wrote %d bytes to %s\n",sizeof(header)+flashsize,outfile); + + close(fh); + + exit(0); + + +} + diff --git a/cfe/cfe/hosttools/mkpcidb.c b/cfe/cfe/hosttools/mkpcidb.c new file mode 100644 index 0000000..fe7d314 --- /dev/null +++ b/cfe/cfe/hosttools/mkpcidb.c @@ -0,0 +1,157 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * PCI Table Generator File: mkpcidb.c + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + * This program munges the PCI table into a form that uses + * fewer embedded pointers. Pointers are evil for the + * relocatable version of CFE since they chew up valuable + * initialized data segment space, and we only have + * 64KB of that. + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#include <stdio.h> + +typedef unsigned short pci_vendor_id_t; +typedef unsigned short pci_product_id_t; + +struct pci_knowndev { + pci_vendor_id_t vendor; + pci_product_id_t product; + int flags; + char *vendorname, *productname; +}; + +#include "../pci/pcidevs.h" +#define PCI_KNOWNDEV_NOPROD 0x01 +#include "../pci/pcidevs_data.h" + + + +struct pci_knowndev2 { + pci_vendor_id_t vendor; + pci_product_id_t product; + int flags; + int vendorname; + int productname; +}; + +#define MAXPCIDEVS 5000 +#define MAXSTRINGTABLE (1024*1024) + +struct pci_knowndev2 knowndevs[MAXPCIDEVS]; +char stringtable[MAXSTRINGTABLE]; +int curstringptr = 0; + +int allocstring(char *string) +{ + int ptr; + + if (!string) return -1; + + ptr = curstringptr; + strcpy(&stringtable[ptr],string); + curstringptr += strlen(string)+1; + return ptr; +} + +int main(int argc,char *argv[]) +{ + struct pci_knowndev2 *outdev; + const struct pci_knowndev *indev; + int cnt = 0; + int idx; + + indev = pci_knowndevs; + outdev = knowndevs; + cnt = 0; + + while (indev->vendorname) { + outdev->vendor = indev->vendor; + outdev->product = indev->product; + outdev->flags = indev->flags; + outdev->vendorname = allocstring(indev->vendorname); + outdev->productname = allocstring(indev->productname); + cnt++; + indev++; + outdev++; + } + + outdev->vendor = 0; + outdev->product = 0; + outdev->flags = 0; + outdev->vendorname = -1; + outdev->productname = -1; + cnt++; + + fprintf(stderr,"%d total devices (%d bytes), %d bytes of strings\n", + cnt,cnt*sizeof(struct pci_knowndev2),curstringptr); + + printf("\n\n\n"); + printf("const static struct pci_knowndev2 _pci_knowndevs[] __attribute__ ((section (\".text\"))) = {\n"); + for (idx = 0; idx < cnt; idx++) { + printf("\t{0x%04X,0x%04X,0x%08X,%d,%d},\n", + knowndevs[idx].vendor, + knowndevs[idx].product, + knowndevs[idx].flags, + knowndevs[idx].vendorname, + knowndevs[idx].productname); + } + printf("};\n\n\n"); + printf("const static char _pci_knowndevs_text[] __attribute__ ((section (\".text\"))) = {\n"); + for (idx = 0; idx < curstringptr; idx++) { + if ((idx % 16) == 0) printf("\t"); + printf("0x%02X,",stringtable[idx]); + if ((idx % 16) == 15) printf("\n"); + } + printf("0};\n\n"); + + printf("static const struct pci_knowndev2 *pci_knowndevs = _pci_knowndevs;\n"); + printf("static const char *pci_knowndevs_text = _pci_knowndevs_text;\n"); + printf("#define PCI_STRING_NULL (-1)\n"); + printf("#define PCI_STRING(x) (&pci_knowndevs_text[(x)])\n\n"); + + + + exit(0); +} + + |