Booting the linux-ppc64 kernel flattened device tree v0.4
On Wed, 2005-06-01 at 18:28 +1000, Benjamin Herrenschmidt wrote: Here is the kernel patch. It applies on top of the various prom_init.c bug fixes that I already posted today on the linuxppc-dev linuxppc64-dev lists (those will be in the next -mm and maybe in 2.6.12). This patch is intended to hit upstream by 2.6.13 Ok, the patch I posted with version 0.4 implementing version 0x10 of the format was broken, here is a fixed version against current linus git as of today: Index: linux-work/arch/ppc64/kernel/prom_init.c === --- linux-work.orig/arch/ppc64/kernel/prom_init.c 2005-06-03 16:52:28.0 +1000 +++ linux-work/arch/ppc64/kernel/prom_init.c2005-06-03 16:58:01.0 +1000 @@ -1534,7 +1534,8 @@ */ #define MAX_PROPERTY_NAME 64 -static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, +static void __init scan_dt_build_strings(phandle node, +unsigned long *mem_start, unsigned long *mem_end) { unsigned long offset = reloc_offset(); @@ -1547,16 +1548,21 @@ /* get and store all property names */ prev_name = RELOC(); for (;;) { - int rc; - /* 64 is max len of name including nul. */ namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); - rc = call_prom(nextprop, 3, 1, node, prev_name, namep); - if (rc != 1) { + if (call_prom(nextprop, 3, 1, node, prev_name, namep) != 1) { /* No more nodes: unwind alloc */ *mem_start = (unsigned long)namep; break; } + + /* skip name */ + if (strcmp(namep, RELOC(name)) == 0) { + *mem_start = (unsigned long)namep; + prev_name = RELOC(name); + continue; + } + /* get/create string entry */ soff = dt_find_string(namep); if (soff != 0) { *mem_start = (unsigned long)namep; @@ -1571,7 +1577,7 @@ /* do all our children */ child = call_prom(child, 1, 1, node); - while (child != (phandle)0) { + while (child != 0) { scan_dt_build_strings(child, mem_start, mem_end); child = call_prom(peer, 1, 1, child); } @@ -1580,16 +1586,13 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, unsigned long *mem_end) { - int l, align; phandle child; - char *namep, *prev_name, *sstart, *p, *ep; + char *namep, *prev_name, *sstart, *p, *ep, *lp, *path; unsigned long soff; unsigned char *valp; unsigned long offset = reloc_offset(); - char pname[MAX_PROPERTY_NAME]; - char *path; - - path = RELOC(prom_scratch); + static char pname[MAX_PROPERTY_NAME]; + int l; dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); @@ -1599,23 +1602,33 @@ namep, *mem_end - *mem_start); if (l = 0) { /* Didn't fit? Get more room. */ - if (l+1 *mem_end - *mem_start) { + if ((l+1) (*mem_end - *mem_start)) { namep = make_room(mem_start, mem_end, l+1, 1); call_prom(package-to-path, 3, 1, node, namep, l); } namep[l] = '\0'; + /* Fixup an Apple bug where they have bogus \0 chars in the * middle of the path in some properties */ for (p = namep, ep = namep + l; p ep; p++) if (*p == '\0') { memmove(p, p+1, ep - p); - ep--; l--; + ep--; l--; p--; } - *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4); + + /* now try to extract the unit name in that mess */ + for (p = namep, lp = NULL; *p; p++) + if (*p == '/') + lp = p + 1; + if (lp != NULL) + memmove(namep, lp, strlen(lp) + 1); + *mem_start = _ALIGN(((unsigned long) namep) + + strlen(namep) + 1, 4); } /* get it again for debugging */ + path = RELOC(prom_scratch); memset(path, 0, PROM_SCRATCH_SIZE); call_prom(package-to-path, 3, 1, node, path, PROM_SCRATCH_SIZE-1); @@ -1623,23 +1636,27 @@ prev_name = RELOC(); sstart = (char *)RELOC(dt_string_start); for (;;) { - int rc; - - rc = call_prom(nextprop, 3, 1, node, prev_name, pname); -
Booting the linux-ppc64 kernel flattened device tree v0.4
On Thu, Jun 02, 2005 at 05:09:18PM +1000, David Gibson wrote: On Wed, Jun 01, 2005 at 06:26:30PM +1000, Benjamin Herrenschmidt wrote: DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies). Here's the fourth version of my document along with new kernel patches for the new improved flattened format, and the first release of the device-tree compiler tool. The patches will be posted as a reply to this email. The compiler, dtc, can be downloaded, the URL is in the document. [snip] IV - dtc, the device tree compiler dtc source code can be found at http://ozlabs.org/~dgibson/dtc/dtc.tar.gz I've just updated the dtc tarball with a new version. Notable changes: - Corrected comment parsing - Corrected handling of #address-cells, #size-cells properties - Input from device tree blobs should actually work now - Corrected autogeneration of name properties in blob/asm output version 0x10 - Added a TODO list And yet another. Notable changes: - Basic generation of the reserve map in blob output, use -R command line option to leave space for a number of reserve map entries to be filled in by bootloader. - Rewrite blob and assembler output to better share code, and produce more readable assembler output. -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/people/dgibson
Booting the linux-ppc64 kernel flattened device tree v0.4
On Wed, 2005-06-01 at 11:58 -0500, Jon Loeliger wrote: On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote: Here's the fourth version of my document along with new kernel patches for the new improved flattened format, and the first release of the device-tree compiler tool. The patches will be posted as a reply to this email. The compiler, dtc, can be downloaded, the URL is in the document. Ben, Does it make sense to do this as well? You mean include lsprop ? Well, I have another version of lsprop hacked here that can generate a source, but dtc can do it too now ... I think we may just make dtc able to output in lsprop format too :) But I'll talk to david (CC'd, he's the author of dtc). Ben.
Booting the linux-ppc64 kernel flattened device tree v0.4
On Wed, 2005-06-01 at 14:54 -0500, Jon Loeliger wrote: On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote: DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies). Here's the fourth version of my document along with new kernel patches for the new improved flattened format, and the first release of the device-tree compiler tool. The patches will be posted as a reply to this email. The compiler, dtc, can be downloaded, the URL is in the document. --- dtc source code can be found at http://ozlabs.org/~dgibson/dtc/dtc.tar.gz Ben, Here are diffs to: - Fix multi-line C-style comments. - Adjust the output of write_tree_source() such that it separates properties and nodes a bit better. Excellent, thanks. Please CC david next time. Ben.
Booting the linux-ppc64 kernel flattened device tree v0.4
On Wed, Jun 01, 2005 at 06:26:30PM +1000, Benjamin Herrenschmidt wrote: DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies). Here's the fourth version of my document along with new kernel patches for the new improved flattened format, and the first release of the device-tree compiler tool. The patches will be posted as a reply to this email. The compiler, dtc, can be downloaded, the URL is in the document. [snip] IV - dtc, the device tree compiler dtc source code can be found at http://ozlabs.org/~dgibson/dtc/dtc.tar.gz I've just updated the dtc tarball with a new version. Notable changes: - Corrected comment parsing - Corrected handling of #address-cells, #size-cells properties - Input from device tree blobs should actually work now - Corrected autogeneration of name properties in blob/asm output version 0x10 - Added a TODO list -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/people/dgibson
Booting the linux-ppc64 kernel flattened device tree v0.4
DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies). Here's the fourth version of my document along with new kernel patches for the new improved flattened format, and the first release of the device-tree compiler tool. The patches will be posted as a reply to this email. The compiler, dtc, can be downloaded, the URL is in the document. --- Booting the Linux/ppc64 kernel without Open Firmware (c) 2005 Benjamin Herrenschmidt benh at kernel.crashing.org, IBM Corp. May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet. May 19, 2005: Rev 0.2 - Add chapter III and bits pieces here or clarifies the fact that a lot of things are optional, the kernel only requires a very small device tree, though it is encouraged to provide an as complete one as possible. May 24, 2005: Rev 0.3 - Precise that DT block has to be in RAM - Misc fixes - Define version 3 and new format version 16 for the DT block (version 16 needs kernel patches, will be fwd separately). String block now has a size, and full path is replaced by unit name for more compactness. linux,phandle is made optional, only nodes that are referenced by other nodes need it. name property is now automatically deduced from the unit name June 1, 2005: Rev 0.4 - Correct confusion between OF_DT_END and OF_DT_END_NODE in structure definition. - Change version 16 format to always align property data to 4 bytes. Since tokens are already aligned, that means no specific required alignement between property size and property data. The old style variable alignment would make it impossible to do simple insertion of properties using memove (thanks Milton for noticing). Updated kernel patch as well - Correct a few more alignement constraints - Add a chapter about the device-tree compiler and the textural representation of the tree that can be compiled by dtc. ToDo: - Add some definitions of interrupt tree (simple/complex) - Add some definitions for pci host bridges I- Introduction === During the recent developpements of the Linux/ppc64 kernel, and more specifically, the addition of new platform types outside of the old IBM pSeries/iSeries pair, it was decided to enforce some strict rules regarding the kernel entry and bootloader - kernel interfaces, in order to avoid the degeneration that has become the ppc32 kernel entry point and the way a new platform should be added to the kernel. The legacy iSeries platform breaks those rules as it predates this scheme, but no new board support will be accepted in the main tree that doesn't follows them properly. The main requirement that will be defined in more details below is the presence of a device-tree whose format is defined after Open Firmware specification. However, in order to make life easier to embedded board vendors, the kernel doesn't require the device-tree to represent every device in the system and only requires some nodes and properties to be present. This will be described in details in section III, but, for example, the kernel does not require you to create a node for every PCI device in the system. It is a requirement to have a node for PCI host bridges in order to provide interrupt routing informations and memory/IO ranges, among others. It is also recommended to define nodes for on chip devices and other busses that doesn't specifically fit in an existing OF specification, like on chip devices, this creates a great flexibility in the way the kernel can them probe those and match drivers to device, without having to hard code all sorts of tables. It also makes it more flexible for board vendors to do minor hardware upgrades without impacting significantly the kernel code or cluttering it with special cases. 1) Entry point -- There is one and one single entry point to the kernel, at the start of the kernel image. That entry point support two calling conventions: a) Boot from Open Firmware. If your firmware is compatible with Open Firmware (IEEE 1275) or provides an OF compatible client interface API (support for interpret callback of forth words isn't required),
Booting the linux-ppc64 kernel flattened device tree v0.4
Here is the kernel patch. It applies on top of the various prom_init.c bug fixes that I already posted today on the linuxppc-dev linuxppc64-dev lists (those will be in the next -mm and maybe in 2.6.12). This patch is intended to hit upstream by 2.6.13 Index: linux-work/arch/ppc64/kernel/prom_init.c === --- linux-work.orig/arch/ppc64/kernel/prom_init.c 2005-06-01 16:02:28.0 +1000 +++ linux-work/arch/ppc64/kernel/prom_init.c2005-06-01 16:07:21.0 +1000 @@ -1514,7 +1514,14 @@ return 0; } -static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, +/* + * The Open Firmware 1275 specification states properties must be 31 bytes or + * less, however not all firmwares obey this. Make it 64 bytes to be safe. + */ +#define MAX_PROPERTY_NAME 64 + +static void __init scan_dt_build_strings(phandle node, +unsigned long *mem_start, unsigned long *mem_end) { unsigned long offset = reloc_offset(); @@ -1527,14 +1534,19 @@ /* get and store all property names */ prev_name = RELOC(); for (;;) { - - /* 32 is max len of name including nul. */ - namep = make_room(mem_start, mem_end, 32, 1); + namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); if (call_prom(nextprop, 3, 1, node, prev_name, namep) = 0) { /* No more nodes: unwind alloc */ *mem_start = (unsigned long)namep; break; } + + /* skip name */ + if (strcmp(namep, RELOC(name)) == 0) { + *mem_start = (unsigned long)namep; + prev_name = RELOC(name); + continue; + } soff = dt_find_string(namep); if (soff != 0) { *mem_start = (unsigned long)namep; @@ -1555,72 +1567,83 @@ } } -/* - * The Open Firmware 1275 specification states properties must be 31 bytes or - * less, however not all firmwares obey this. Make it 64 bytes to be safe. - */ -#define MAX_PROPERTY_NAME 64 - static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, unsigned long *mem_end) { - int l, align; phandle child; - char *namep, *prev_name, *sstart, *p, *ep; + char *namep, *prev_name, *sstart, *p, *ep, *lp, *path; unsigned long soff; unsigned char *valp; unsigned long offset = reloc_offset(); - char pname[MAX_PROPERTY_NAME]; - char *path; - - path = RELOC(prom_scratch); + static char pname[MAX_PROPERTY_NAME] __initdata; + int l; dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); - /* get the node's full name */ + /* get the node's full name for debugging */ + path = RELOC(prom_scratch); + memset(path, 0, PROM_SCRATCH_SIZE); + call_prom(package-to-path, 3, 1, node, path, PROM_SCRATCH_SIZE-1); + prom_debug( %s\n, path); + + /* get the node's full name for actual use */ namep = (char *)*mem_start; l = call_prom(package-to-path, 3, 1, node, namep, *mem_end - *mem_start); if (l = 0) { + int had_fixup = 0; + /* Didn't fit? Get more room. */ if (l+1 *mem_end - *mem_start) { namep = make_room(mem_start, mem_end, l+1, 1); call_prom(package-to-path, 3, 1, node, namep, l); } - namep[l] = '\0'; - /* Fixup an Apple bug where they have bogus \0 chars in the -* middle of the path in some properties -*/ - for (p = namep, ep = namep + l; p ep; p++) - if (*p == '\0') { - memmove(p, p+1, ep - p); - ep--; l--; - } - *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4); + ep = namep + l; + *ep = '\0'; + /* now try to find the unit name in that mess */ + for (p = namep, lp = NULL; p ep; p++) { + if (*p == '/') + lp = p + 1; + /* bug fix: apple's OF has a funny bug where they have +* a '\0' in the name/path string of some nodes. +* We fix that up here +*/ + if (*p == '\0') { + memmove(p, p+1, ep - p); + ep--; l--; + had_fixup = 1; + } + } +
Booting the linux-ppc64 kernel flattened device tree v0.4
On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote: Here's the fourth version of my document along with new kernel patches for the new improved flattened format, and the first release of the device-tree compiler tool. The patches will be posted as a reply to this email. The compiler, dtc, can be downloaded, the URL is in the document. Ben, Does it make sense to do this as well? Thanks, jdl diff -Nur dtc.orig/lsprop.c dtc/lsprop.c --- dtc.orig/lsprop.c 1969-12-31 18:00:00.0 -0600 +++ dtc/lsprop.c2005-06-01 11:43:01.02000 -0500 @@ -0,0 +1,221 @@ +#include stdio.h +#include stdlib.h +#include unistd.h +#include sys/stat.h +#include sys/types.h +#include dirent.h + +int recurse; +int maxbytes = 128; +int words_per_line = 0; +char *buf; + +void lsprop(FILE *f, char *name); +void lsdir(char *name); + +main(int ac, char **av) +{ +FILE *f; +int i; +struct stat sb; +char *endp; + +while ((i = getopt(ac, av, Rm:w:)) != EOF) { + switch (i) { + case 'R': + recurse = 1; + break; + case 'm': + maxbytes = strtol(optarg, endp, 0); + if (endp == optarg) { + fprintf(stderr, %s: bad argument (%s) to -m option\n, av[0], + optarg); + exit(1); + } + maxbytes = (maxbytes + 15) -16; + break; + case 'w': + words_per_line = strtol(optarg, endp, 0); + if (endp == optarg) { + fprintf(stderr, %s: bad argument (%s) to -w option\n, + av[0], optarg); + exit(1); + } + break; + } +} + +buf = malloc(maxbytes); +if (buf == 0) { + fprintf(stderr, %s: virtual memory exhausted\n, av[0]); + exit(1); +} + +if (optind == ac) + lsdir(.); +else + for (i = optind; i ac; ++i) { + if (stat(av[i], sb) 0) { + perror(av[i]); + continue; + } + if (S_ISREG(sb.st_mode)) { + f = fopen(av[i], r); + if (f == NULL) { + perror(av[i]); + continue; + } + lsprop(f, av[i]); + fclose(f); + } else if (S_ISDIR(sb.st_mode)) { + lsdir(av[i]); + } + } +exit(0); +} + +void lsdir(char *name) +{ +DIR *d; +struct dirent *de; +char *p, *q; +struct stat sb; +FILE *f; +int np = 0; + +d = opendir(name); +if (d == NULL) { + perror(name); + return; +} + +p = malloc(strlen(name) + 520); +if (p == 0) { + fprintf(stderr, %s: virtual memory exhausted\n, name); + closedir(d); + return; +} +strcpy(p, name); +q = p + strlen(p); +while (q p q[-1] == '/') + --q; +if (q == p + 1 p[0] == '.') + q = p; +else + *q++ = '/'; + +while ((de = readdir(d)) != NULL) { + if (strcmp(de-d_name, .) == 0 || strcmp(de-d_name, ..) == 0) + continue; + strcpy(q, de-d_name); + if (stat(p, sb) 0) { + perror(p); + continue; + } + if (S_ISREG(sb.st_mode)) { + f = fopen(p, r); + if (f == NULL) { + perror(p); + } else { + lsprop(f, de-d_name); + fclose(f); + ++np; + } + } +} +rewinddir(d); +while ((de = readdir(d)) != NULL) { + if (strcmp(de-d_name, .) == 0 || strcmp(de-d_name, ..) == 0) + continue; + strcpy(q, de-d_name); + if (lstat(p, sb) 0) { + perror(p); + continue; + } + if (S_ISDIR(sb.st_mode)) { + if (np) + printf(\n); + printf(%s:\n, p); + lsdir(p); + ++np; + } +} +free(p); +closedir(d); +} + +void lsprop(FILE *f, char *name) +{ +int n, nw, npl, i, j; + +n = fread(buf, 1, maxbytes, f); +if (n 0) { + printf(%s: read error\n, name); + return; +} +printf(%-16s, name); +if (strlen(name) 16) + printf(\n\t\t); +for (i = 0; i n; ++i) + if (buf[i] = 0x7f || + (buf[i] 0x20 buf[i] != '\r' buf[i] != '\n' + buf[i] != '\t' buf[i] != 0)) + break; +if (i == n n != 0 (n == 1 || buf[0] != 0) buf[n-1] == 0) { + printf( \); + for (i = 0; i n - 1; ++i) + if (buf[i] == 0) + printf(\\n\t\t \); + else if (buf[i] == '\r' || buf[i] == '\n') + printf(\n\t\t ); + else + putchar(buf[i]); + putchar(''); +} else if ((n 3) == 0) { + nw = n 2; + if (nw == 1) { + i = *(int *)buf; + printf( %.8x, i); + if (i -0x1 !(i = 0 i = 9)) + printf( (%d), i); + } else { + npl = words_per_line; + if (npl
Booting the linux-ppc64 kernel flattened device tree v0.4
On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote: DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies). Here's the fourth version of my document along with new kernel patches for the new improved flattened format, and the first release of the device-tree compiler tool. The patches will be posted as a reply to this email. The compiler, dtc, can be downloaded, the URL is in the document. --- dtc source code can be found at http://ozlabs.org/~dgibson/dtc/dtc.tar.gz Ben, Here are diffs to: - Fix multi-line C-style comments. - Adjust the output of write_tree_source() such that it separates properties and nodes a bit better. Thanks, jdl diff -u dtc.orig/dtc-lexer.l dtc/dtc-lexer.l --- dtc.orig/dtc-lexer.l2005-06-01 11:44:29.02000 -0500 +++ dtc/dtc-lexer.l 2005-06-01 13:39:56.01000 -0500 @@ -34,8 +34,6 @@ #include y.tab.h -#undef LEXDEBUG1 - %} \[^]*\ { @@ -102,7 +100,7 @@ *{WS}+ /* eat whitespace */ -*\/\*[^*]*(\*[^/][^*])*\*\/ /* eat comments */ +*\/\*([^*]|\**[^*/])*\*+\/ /* eat C comments */ *\/\/.*\n/* eat line comments */ diff -u dtc.orig/treesource.c dtc/treesource.c --- dtc.orig/treesource.c 2005-06-01 11:44:29.02000 -0500 +++ dtc/treesource.c2005-06-01 13:58:33.01000 -0500 @@ -131,10 +131,16 @@ break; } } - fprintf(f, \n); + if (tree-children) { + fprintf(f, \n); + } for_each_child(tree, child) { write_tree_source(f, child, level+1); } write_prefix(f, level); fprintf(f, };\n); + + if (tree-next_sibling) { + fprintf(f, \n); + } }