bootwrapper: kexec and external payloads
Subsystems (2)
cover bootwrapper: kexec and external payloads
The following series of 15 patches implement
support for 64-bit powerpc zImage to be loaded by kexec-tools
the wrapper uses the same startup interface as the kernel
support for obtaining the kernel externally to the zImage link
including via searching for a path string in initramfs
This is the third round of posting for most of the patches, which have been rebased to apply to for-2.6.24, and I ask they be considered for inclusion therein.
I have ordered the series to apply needed functionality to get usable code for similar enviornments before fleshing out the feature set I am using. If desired I can reorder and rediff as requested. (for example, adding the smp hook could go with the smp marshalling support). The last patch is only needed for the qemu pathes below.
Following the series are an additonal 2 patches to provide experimental platform support for running under qemu with its exiting powerpc prep emulation. One patch provides the support necessary to build the kernel, the second patch provides the wrapper changes and device tree to boot, including bulding a "rom" image. Once the rom is built, it can start a vmlinux elf when loaded into memory by qemu.
Thanks for your consideration,
milton
PATCH 1/15 boot: find initrd location from device-tree
Some platforms have a boot agent that can create or modify properties in the device-tree and load images into memory. Provide a helper to set loader_info used by prep_initrd().
---
re 12168
rediffed types.h, offset in ops.h
arch/powerpc/boot/ops.h +1 -0
@@ -163,6 +163,7 @@ void dt_fixup_clock(const char *path, u3void __dt_fixup_mac_addresses (u32 startindex, ...);#define dt_fixup_mac_addresses (...) \ __dt_fixup_mac_addresses(0, __VA_ARGS__, NULL) +void dt_find_initrd (void );static inline void *find_node_by_linuxphandle (const u32 linuxphandle)
arch/powerpc/boot/types.h +2 -0
@@ -12,6 +12,8 @@ typedef short s16;typedef int s32 ;typedef long long s64 ; +#define UINT_MAX 0xFFFFFFFF +#define min (x,y) ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \
arch/powerpc/boot/devtree.c +66 -0
75 lines not on this page · raw message
Re: [PATCH 1/15] boot: find initrd location from device-tree
Quoted 6 lines · Milton Miller
Some platforms have a boot agent that can create or modify properties in the device-tree and load images into memory. Provide a helper to set
loader_infoused byprep_initrd().Signed-off-by Milton Miller <[email protected]>Acked-by David Gibson <[email protected]>
Hrm, despite my earlier ack, I'm going to whinge about a few nits here.
Quoted 21 lines
---
re 12168
rediffedtypes.h, offset inops.hIndex:
kernel/arch/powerpc/boot/ops.h
===================================================================arch/powerpc/boot/ops.h +1
-0@@ -163,6 +163,7 @@ void dt_fixup_clock(const char *path, u3void __dt_fixup_mac_addresses (u32 startindex, ...);#define dt_fixup_mac_addresses (...) \ __dt_fixup_mac_addresses(0, __VA_ARGS__, NULL) +void dt_find_initrd (void );static inline void *find_node_by_linuxphandle (const u32 linuxphandle)Index:
kernel/arch/powerpc/boot/types.h
===================================================================
arch/powerpc/boot/types.h typedef short s16; · line 15
Quoted 4 lines
arch/powerpc/boot/types.h +1
-0@@ -12,6 +12,8 @@ typedef short s16;typedef int s32 ;typedef long long s64 ; +#define UINT_MAX 0xFFFFFFFF
I actually don't like this constant - at the point you compare you care, explicitly, about the value not being over 32-bits, rather than whether it fits a uint, so the named constant is more misleading than helpful.
Quoted 20 lines
arch/powerpc/boot/types.h +1
-0+#define min (x,y) ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \Index:
kernel/arch/powerpc/boot/devtree.c
===================================================================arch/powerpc/boot/devtree.c +1
-0@@ -1,6 +1,7 @@/* * devtree.c - convenience functions for device tree manipulation * Copyright 2007 David Gibson, IBM Corporation. +* Copyright 2007 Milton Miller, IBM Corporation. * Copyright (c) 2007 Freescale Semiconductor, Inc. * * Authors: David Gibson <[email protected]> @@ -333,3 +334,68 @@ int dt_is_compatible(void *node, const creturn 0 ; }
arch/powerpc/boot/devtree.c int dt_is_compatible(void *node, const c · line 346
Quoted 10 lines
arch/powerpc/boot/devtree.c +10
-0+ +/** +* dt_find_initrd - set loader initrd location based on existing properties +* +* finds the linux,initrd-start and linux,initrd-end properties in +* the /chosen node and sets the loader initrd fields accordingly. +* +* Use this if your loader sets the properties to allow other code to +* relocate the tree and/or cause r3 and r4 to be set on true OF +* platforms.
I am unable to make sense of the paragraph above.
arch/powerpc/boot/devtree.c int dt_is_compatible(void *node, const c · line 354
Quoted 8 lines
arch/powerpc/boot/devtree.c +8
-0+*/ +void dt_find_initrd (void ) +{ +int rc; +unsigned long long initrd_start, initrd_end; +void *devp; +static const char start_prop[] ="linux,initrd-start" ; +static const char end_prop[] ="linux,initrd-end" ;
I think these constants are more obscuring than useful.
arch/powerpc/boot/devtree.c int dt_is_compatible(void *node, const c · line 359
Quoted 5 lines
arch/powerpc/boot/devtree.c +5
-0+ + devp =finddevice ("/chosen" ); +if (! devp) { +return ; + }
CodingStyle would not put { } here.
Quoted 11 lines
arch/powerpc/boot/devtree.c +10
-0+ + rc =getprop (devp, start_prop, &initrd_start,sizeof (initrd_start)); +if (rc <0 ) +return ;/* not found */ +/* The properties had to be 8 bytes until 2.6.22 */ +if (rc ==sizeof (unsigned long )) { +unsigned long tmp; +memcpy (&tmp, &initrd_start, rc); + initrd_start = tmp; + }else if (rc !=sizeof (initrd_start)) {/* now they can be 4 */
Right. 8 bytes and 4 bytes, so you should be using explicit length types instead of long and long long.
arch/powerpc/boot/devtree.c
Quoted 2 lines
arch/powerpc/boot/devtree.c +2
-0+printf ("unexpected length of %s in /chosen!\n\r" , start_prop); +return ;
All these printf() / return stanzas add a lot of verbosity to this function. Any way they can be consolidated a bit, maybe a single error path that just prints the property values, so the user can figure out what was wrong with them.
Quoted 35 lines
arch/powerpc/boot/devtree.c +30
-0+ } + + rc =getprop (devp, end_prop, &initrd_end,sizeof (initrd_end)); +if (rc <0 ) { +printf ("chosen has %s but no %s!\n\r" , start_prop, end_prop); +return ; + } +if (rc ==sizeof (unsigned long )) { +unsigned long tmp; +memcpy (&tmp, &initrd_end, rc); + initrd_end = tmp; + }else if (rc !=sizeof (initrd_end)) { +printf ("unexpected length of %s in /chosen!\n\r" , end_prop); +return ; + } + +/* Check for presence, ignore if (partially) loaded above 32 bits */ +if (initrd_start == initrd_end) { +printf ("ignoring empty device-tree supplied initrd\n" ); + }else if (initrd_start > initrd_end) { +printf ("ignoring device-tree supplied initrd: start 0x%llx" +" > end 0x%llx \n" , initrd_start, initrd_end); + }else if (initrd_end >UINT_MAX ) { +printf ("ignoring device-tree supplied initrd:" +" end 0x%llx > 32 bits\n" , initrd_end); + }else { + loader_info.initrd_addr = initrd_start; + loader_info.initrd_size = initrd_end - initrd_start; + } +}_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-dev
Signature · 4 lines
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/~dgibson
Re: [PATCH 1/15] boot: find initrd location from device-tree
Quoted 35 lines · David Gibson
Quoted 6 lines · Milton Miller
Some platforms have a boot agent that can create or modify properties in the device-tree and load images into memory. Provide a helper to set
loader_infoused byprep_initrd().Signed-off-by Milton Miller <[email protected]>Acked-by David Gibson <[email protected]>Hrm, despite my earlier ack, I'm going to whinge about a few nits here.
Quoted 24 lines
---
re 12168
rediffedtypes.h, offset inops.hIndex:
kernel/arch/powerpc/boot/ops.h
===================================================================
---kernel.orig/arch/powerpc/boot/ops.h2007-09-17 22:12:47.000000000
-0500 +++kernel/arch/powerpc/boot/ops.h2007-09-17 22:12:51.000000000
-0500 @@ -163,6 +163,7 @@ void dt_fixup_clock(const char *path, u3
void__dt_fixup_mac_addresses(u32 startindex, ...); #definedt_fixup_mac_addresses(...)\arch/powerpc/boot/ops.h +1
-0__dt_fixup_mac_addresses(0, __VA_ARGS__, NULL) +void dt_find_initrd (void );static inline void *find_node_by_linuxphandle (const u32 linuxphandle)Index:
kernel/arch/powerpc/boot/types.h
===================================================================
---kernel.orig/arch/powerpc/boot/types.h2007-09-17 22:12:47.000000000
-0500 +++kernel/arch/powerpc/boot/types.h2007-09-17 22:12:51.000000000
-0500 @@ -12,6 +12,8 @@ typedef short s16;
typedef int s32;
typedef long long s64;
Quoted 6 lines
Quoted 1 line
+#define
UINT_MAX0xFFFFFFFFI actually don't like this constant - at the point you compare you care, explicitly, about the value not being over 32-bits, rather than whether it fits a uint, so the named constant is more misleading than helpful.
Except int and uint are 32 bits on all targets, due to unix standardizing on LP64:
http://www.unix.org/whitepapers/64bit.html
http://www.unix.org/version2/whatsnew/lp64_wp.html
Quoted 11 lines
Quoted 9 lines
+/**
+ *dt_find_initrd- set loader initrd location based on existing properties + *
+ * finds the linux,initrd-start and linux,initrd-end properties in
+ * the /chosen node and sets the loader initrd fields accordingly.
+ *
+ * Use this if your loader sets the properties to allow other code to
+ * relocate the tree and/or cause r3 and r4 to be set on true OF
+ * platforms.I am unable to make sense of the paragraph above.
I think this means it finds the initrd location from the device tree (supplied by your firmware or bootloader) rather than from the kernel command line the way all the other platforms do.
Rob
Signature · 2 lines
"One of my most productive days was throwing away 1000 lines of code." - Ken Thompson.
Re: [PATCH 1/15] boot: find initrd location from device-tree
In reply to David GibsonQuoted 38 lines · David Gibson
Quoted 6 lines · Milton Miller
Some platforms have a boot agent that can create or modify properties in the device-tree and load images into memory. Provide a helper to set
loader_infoused byprep_initrd().Signed-off-by Milton Miller <[email protected]>Acked-by David Gibson <[email protected]>Hrm, despite my earlier ack, I'm going to whinge about a few nits here.
Quoted 27 lines
---
re 12168
rediffedtypes.h, offset inops.hIndex:
kernel/arch/powerpc/boot/ops.h
===================================================================
---kernel.orig/arch/powerpc/boot/ops.h2007-09-17 22:12:47.000000000
-0500
+++kernel/arch/powerpc/boot/ops.h2007-09-17 22:12:51.000000000 -0500arch/powerpc/boot/ops.h +1
-0@@ -163,6 +163,7 @@ void dt_fixup_clock(const char *path, u3void __dt_fixup_mac_addresses (u32 startindex, ...);#define dt_fixup_mac_addresses (...) \ __dt_fixup_mac_addresses(0, __VA_ARGS__, NULL) +void dt_find_initrd (void );static inline void *find_node_by_linuxphandle (const u32 linuxphandle)Index:
kernel/arch/powerpc/boot/types.h
===================================================================
---kernel.orig/arch/powerpc/boot/types.h2007-09-17
22:12:47.000000000 -0500
+++kernel/arch/powerpc/boot/types.h2007-09-17 22:12:51.000000000
-0500arch/powerpc/boot/types.h +0
-0@@ -12,6 +12,8 @@ typedef short s16;typedef int s32 ;typedef long long s64 ;
Quoted 6 lines
arch/powerpc/boot/types.h typedef short s16; · line 15
Quoted 1 line
arch/powerpc/boot/types.h +1
-0+#define UINT_MAX 0xFFFFFFFFI actually don't like this constant - at the point you compare you care, explicitly, about the value not being over 32-bits, rather than whether it fits a uint, so the named constant is more misleading than helpful.
Arguable, I don't like counting F's or zeros in C code.
It is used as the max address that the wrapper deals with, both here and memranges, which happens to be 32 bits.
Actually it cares about overflowing the unsigned long in loader_info, not that the address fits in 32 bits.
So it should be ULONG_MAX now (malloc and all the address code was changed to use unsigned long instead of unsigned int since the patch was written).
And dt_xlate needs the same information. Its is using a hardcoded 64 bit constant to provide the a simiar check.
Quoted 20 lines
Quoted 20 lines
arch/powerpc/boot/types.h +1
-0+#define min (x,y) ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \Index:
kernel/arch/powerpc/boot/devtree.c
===================================================================
---kernel.orig/arch/powerpc/boot/devtree.c2007-09-17
22:12:47.000000000 -0500
+++kernel/arch/powerpc/boot/devtree.c2007-09-17 22:12:51.000000000
-0500arch/powerpc/boot/devtree.c +1
-0@@ -1,6 +1,7 @@/* * devtree.c - convenience functions for device tree manipulation * Copyright 2007 David Gibson, IBM Corporation. +* Copyright 2007 Milton Miller, IBM Corporation. * Copyright (c) 2007 Freescale Semiconductor, Inc. * * Authors: David Gibson <[email protected]> @@ -333,3 +334,68 @@ int dt_is_compatible(void *node, const c
Quoted 15 lines
Quoted 5 lines
arch/powerpc/boot/devtree.c +3
-0return 0 ; } + +/** +* dt_find_initrd - set loader initrd location based on existing Quoted 8 lines
properties
+ *
+ * finds the linux,initrd-start and linux,initrd-end properties in
+ * the /chosen node and sets the loader initrd fields accordingly.
+ *
+ * Use this if your loader sets the properties to allow other code to
+ * relocate the tree and/or cause r3 and r4 to be set on true OF
+ * platforms.I am unable to make sense of the paragraph above.
The phrase "relocate the tree" should be "relocate the initrd", which the wrapper will do if it located below vmlinux.size. Also, r3 and r4 need to be set when booting the kernel from a client interface with an initrd so it can take it into consideration when choosing the location to build the flat tree.
How about:
Filling in the loader info allows main.c to be aware of the initrd, meaning prep_initrd will move the initrd if it will be overwritten when the kernel is copied to its runtime location. In addition, if you are booting the kernel from a client interface instead of a flat device tree, this also causes r3 and r4 to be set so the kernel can avoid overwriting the initrd when creating the flat tree.
Quoted 11 lines
arch/powerpc/boot/devtree.c int dt_is_compatible(void *node, const c · line 354
Quoted 9 lines
+ */
arch/powerpc/boot/devtree.c +7
-0+void dt_find_initrd (void ) +{ +int rc; +unsigned long long initrd_start, initrd_end; +void *devp; +static const char start_prop[] ="linux,initrd-start" ; +static const char end_prop[] ="linux,initrd-end" ;I think these constants are more obscuring than useful.
They are useful to the extent they reduce the number of source characters causing about 8 less line wraps. Since they are used multiple places, the compiler only needs to emit one copy of this byte sequence. Admitedly you made this point in a prior review.
Quoted 8 lines
arch/powerpc/boot/devtree.c int dt_is_compatible(void *node, const c · line 359
Quoted 6 lines
arch/powerpc/boot/devtree.c +5
-0+ + devp =finddevice ("/chosen" ); +if (! devp) { +return ; + }CodingStyle would not put { } here.
Yea, nit. not sure why I have the braces there, I usually follow that one. And what's that space doing after !?
Quoted 15 lines
Quoted 11 lines
arch/powerpc/boot/devtree.c +10
-0+ + rc =getprop (devp, start_prop, &initrd_start,sizeof (initrd_start)); +if (rc <0 ) +return ;/* not found */ +/* The properties had to be 8 bytes until 2.6.22 */ +if (rc ==sizeof (unsigned long )) { +unsigned long tmp; +memcpy (&tmp, &initrd_start, rc); + initrd_start = tmp; + }else if (rc !=sizeof (initrd_start)) {/* now they Quoted 1 line
can be 4 */
Right. 8 bytes and 4 bytes, so you should be using explicit length types instead of long and long long.
Ok, I guess we ahve u32 and u64 in types.h now. But there is other code in the wrapper that assumes its compiled 32 bit ILP.
Quoted 8 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ printf("unexpected length of %s in /chosen!\n\r", start_prop); + return;All these
printf()/ return stanzas add a lot of verbosity to this function. Any way they can be consolidated a bit, maybe a single error path that just prints the property values, so the user can figure out what was wrong with them.
On a prior review I got asked to split the reasons for ingoring the values below (the > 32 bit address from end < start cases). Admitedly without all the detailed errors the justification for the string varables is reduced.
Quoted 43 lines
Quoted 36 lines
arch/powerpc/boot/devtree.c +30
-0+ } + + rc =getprop (devp, end_prop, &initrd_end,sizeof (initrd_end)); +if (rc <0 ) { +printf ("chosen has %s but no %s!\n\r" , start_prop, end_prop); +return ; + } +if (rc ==sizeof (unsigned long )) { +unsigned long tmp; +memcpy (&tmp, &initrd_end, rc); + initrd_end = tmp; + }else if (rc !=sizeof (initrd_end)) { +printf ("unexpected length of %s in /chosen!\n\r" , end_prop); +return ; + } + +/* Check for presence, ignore if (partially) loaded above 32 bits */ +if (initrd_start == initrd_end) { +printf ("ignoring empty device-tree supplied initrd\n" ); + }else if (initrd_start > initrd_end) { +printf ("ignoring device-tree supplied initrd: start 0x%llx" +" > end 0x%llx \n" , initrd_start, initrd_end); + }else if (initrd_end >UINT_MAX ) { +printf ("ignoring device-tree supplied initrd:" +" end 0x%llx > 32 bits\n" , initrd_end); + }else { + loader_info.initrd_addr = initrd_start; + loader_info.initrd_size = initrd_end - initrd_start; + } +}_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-devSignature · 4 lines
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/~dgibson
Re: [PATCH 1/15] boot: find initrd location from device-tree
Quoted 42 lines · Milton Miller
Quoted 39 lines · David Gibson
Quoted 7 lines · Milton Miller
Some platforms have a boot agent that can create or modify properties in
the device-tree and load images into memory. Provide a helper to setloader_infoused byprep_initrd().Signed-off-by Milton Miller <[email protected]>Acked-by David Gibson <[email protected]>Hrm, despite my earlier ack, I'm going to whinge about a few nits here.
Quoted 27 lines
---
re 12168
rediffedtypes.h, offset inops.hIndex:
kernel/arch/powerpc/boot/ops.h
===================================================================
---kernel.orig/arch/powerpc/boot/ops.h2007-09-17 22:12:47.000000000
-0500
+++kernel/arch/powerpc/boot/ops.h2007-09-17 22:12:51.000000000 -0500arch/powerpc/boot/ops.h +1
-0@@ -163,6 +163,7 @@ void dt_fixup_clock(const char *path, u3void __dt_fixup_mac_addresses (u32 startindex, ...);#define dt_fixup_mac_addresses (...) \ __dt_fixup_mac_addresses(0, __VA_ARGS__, NULL) +void dt_find_initrd (void );static inline void *find_node_by_linuxphandle (const u32 linuxphandle)Index:
kernel/arch/powerpc/boot/types.h
===================================================================
---kernel.orig/arch/powerpc/boot/types.h2007-09-17
22:12:47.000000000 -0500
+++kernel/arch/powerpc/boot/types.h2007-09-17 22:12:51.000000000
-0500arch/powerpc/boot/types.h +0
-0@@ -12,6 +12,8 @@ typedef short s16;typedef int s32 ;typedef long long s64 ;
Quoted 8 lines
Quoted 6 lines
arch/powerpc/boot/types.h typedef short s16; · line 15
Quoted 1 line
arch/powerpc/boot/types.h +1
-0+#define UINT_MAX 0xFFFFFFFFI actually don't like this constant - at the point you compare you care, explicitly, about the value not being over 32-bits, rather than whether it fits a uint, so the named constant is more misleading than helpful.
Arguable, I don't like counting F's or zeros in C code.
So check if (addr >> 32) is non-zero.
Quoted 2 lines
It is used as the max address that the wrapper deals with, both here and memranges, which happens to be 32 bits.
Right and the reasons for that being the value it is are not because it also hapeens to be the max uint *or* ulong.
Quoted 53 lines
Actually it cares about overflowing the unsigned long in
loader_info, not that the address fits in 32 bits.So it should be
ULONG_MAXnow (malloc and all the address code was changed to use unsigned long instead of unsigned int since the patch was written).And
dt_xlateneeds the same information. Its is using a hardcoded 64 bit constant to provide the a simiar check.Quoted 20 lines
Quoted 20 lines
arch/powerpc/boot/types.h +1
-0+#define min (x,y) ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \Index:
kernel/arch/powerpc/boot/devtree.c
===================================================================
---kernel.orig/arch/powerpc/boot/devtree.c2007-09-17
22:12:47.000000000 -0500
+++kernel/arch/powerpc/boot/devtree.c2007-09-17 22:12:51.000000000
-0500arch/powerpc/boot/devtree.c +1
-0@@ -1,6 +1,7 @@/* * devtree.c - convenience functions for device tree manipulation * Copyright 2007 David Gibson, IBM Corporation. +* Copyright 2007 Milton Miller, IBM Corporation. * Copyright (c) 2007 Freescale Semiconductor, Inc. * * Authors: David Gibson <[email protected]> @@ -333,3 +334,68 @@ int dt_is_compatible(void *node, const cQuoted 15 lines
Quoted 5 lines
arch/powerpc/boot/devtree.c +3
-0return 0 ; } + +/** +* dt_find_initrd - set loader initrd location based on existing Quoted 8 lines
properties
+ *
+ * finds the linux,initrd-start and linux,initrd-end properties in
+ * the /chosen node and sets the loader initrd fields accordingly.
+ *
+ * Use this if your loader sets the properties to allow other code to
+ * relocate the tree and/or cause r3 and r4 to be set on true OF
+ * platforms.I am unable to make sense of the paragraph above.
The phrase "relocate the tree" should be "relocate the initrd", which the wrapper will do if it located below vmlinux.size. Also, r3 and r4 need to be set when booting the kernel from a client interface with an initrd so it can take it into consideration when choosing the location to build the flat tree.
Quoted 8 lines
How about:
Filling in the loader info allows
main.cto be aware of the initrd, meaningprep_initrdwill move the initrd if it will be overwritten when the kernel is copied to its runtime location. In addition, if you are booting the kernel from a client interface instead of a flat device tree, this also causes r3 and r4 to be set so the kernel can avoid overwriting the initrd when creating the flat tree.
Clearer, but I still don't see that it says anything useful - "finds the initrd from the devtree and does all the things that are supposed to be done with an initrd" - which is implied in the previous paragraph.
Quoted 13 lines
Quoted 12 lines
arch/powerpc/boot/devtree.c int dt_is_compatible(void *node, const c · line 354
Quoted 10 lines
+ */
arch/powerpc/boot/devtree.c +7
-0+void dt_find_initrd (void ) +{ +int rc; +unsigned long long initrd_start, initrd_end; +void *devp; +static const char start_prop[] ="linux,initrd-start" ; +static const char end_prop[] ="linux,initrd-end" ;I think these constants are more obscuring than useful.
Quoted 4 lines
They are useful to the extent they reduce the number of source characters causing about 8 less line wraps. Since they are used multiple places, the compiler only needs to emit one copy of this byte sequence. Admitedly you made this point in a prior review.
The compiler is perfectly capable of folding identical string constants.
Quoted 27 lines
Quoted 7 lines
arch/powerpc/boot/devtree.c int dt_is_compatible(void *node, const c · line 359
Quoted 5 lines
arch/powerpc/boot/devtree.c +5
-0+ + devp =finddevice ("/chosen" ); +if (! devp) { +return ; + }CodingStyle would not put { } here.
Yea, nit. not sure why I have the braces there, I usually follow that one. And what's that space doing after !?
Quoted 15 lines
Quoted 11 lines
arch/powerpc/boot/devtree.c +10
-0+ + rc =getprop (devp, start_prop, &initrd_start,sizeof (initrd_start)); +if (rc <0 ) +return ;/* not found */ +/* The properties had to be 8 bytes until 2.6.22 */ +if (rc ==sizeof (unsigned long )) { +unsigned long tmp; +memcpy (&tmp, &initrd_start, rc); + initrd_start = tmp; + }else if (rc !=sizeof (initrd_start)) {/* now they Quoted 1 line
can be 4 */
Right. 8 bytes and 4 bytes, so you should be using explicit length types instead of long and long long.
Quoted 2 lines
Ok, I guess we ahve u32 and u64 in
types.hnow. But there is other code in the wrapper that assumes its compiled 32 bit ILP.
Yes, but that's no reason to propagate the sin.
Quoted 8 lines
Quoted 7 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ printf("unexpected length of %s in /chosen!\n\r", start_prop); + return;All these
printf()/ return stanzas add a lot of verbosity to this function. Any way they can be consolidated a bit, maybe a single error path that just prints the property values, so the user can figure out what was wrong with them.
Quoted 4 lines
On a prior review I got asked to split the reasons for ingoring the values below (the > 32 bit address from end < start cases). Admitedly without all the detailed errors the justification for the string varables is reduced.
Hrm. Well, I can't say I'm entirely convinced either way on this one. I guess I'll think about it again once the rest is cleaned up.
Signature · 4 lines
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/~dgibson
Re: [PATCH 1/15] boot: find initrd location from device-tree
Quoted 55 lines · David Gibson
Quoted 45 lines · Milton Miller
Quoted 42 lines · David Gibson
Quoted 7 lines · Milton Miller
Some platforms have a boot agent that can create or modify properties in
the device-tree and load images into memory. Provide a helper to setloader_infoused byprep_initrd().Signed-off-by Milton Miller <[email protected]>Acked-by David Gibson <[email protected]>Hrm, despite my earlier ack, I'm going to whinge about a few nits here.
Quoted 30 lines
---
re 12168
rediffedtypes.h, offset inops.hIndex:
kernel/arch/powerpc/boot/ops.h
===================================================================
---kernel.orig/arch/powerpc/boot/ops.h2007-09-17
22:12:47.000000000
-0500
+++kernel/arch/powerpc/boot/ops.h2007-09-17 22:12:51.000000000
-0500arch/powerpc/boot/ops.h +1
-0@@ -163,6 +163,7 @@ void dt_fixup_clock(const char *path, u3void __dt_fixup_mac_addresses (u32 startindex, ...);#define dt_fixup_mac_addresses (...) \ __dt_fixup_mac_addresses(0, __VA_ARGS__, NULL) +void dt_find_initrd (void ); static inline void *find_node_by_linuxphandle(const u32linuxphandle)
Index:kernel/arch/powerpc/boot/types.h
===================================================================
---kernel.orig/arch/powerpc/boot/types.h2007-09-17
22:12:47.000000000 -0500
+++kernel/arch/powerpc/boot/types.h2007-09-17 22:12:51.000000000
-0500arch/powerpc/boot/types.h +0
-0@@ -12,6 +12,8 @@ typedef short s16;typedef int s32 ;typedef long long s64 ;Quoted 8 lines
Quoted 6 lines
arch/powerpc/boot/types.h typedef short s16; · line 15
Quoted 1 line
arch/powerpc/boot/types.h +1
-0+#define UINT_MAX 0xFFFFFFFFI actually don't like this constant - at the point you compare you care, explicitly, about the value not being over 32-bits, rather than whether it fits a uint, so the named constant is more misleading than helpful.
Arguable, I don't like counting F's or zeros in C code.
Quoted 7 lines
So check if (addr >> 32) is non-zero.
Quoted 2 lines
It is used as the max address that the wrapper deals with, both here and memranges, which happens to be 32 bits.
Right and the reasons for that being the value it is are not because it also hapeens to be the max uint *or* ulong.
Huh? the code is checking that the value will fit in the ulongs that are the type that stores this value in the struct. Are you aruging for max_ptr_type? If the code were compiled LP64 then it would not need to check that the address was 32 bits. Here you say "check for 32 bits", while below ...
Quoted 64 lines
Quoted 55 lines
Actually it cares about overflowing the unsigned long in
loader_info, not that the address fits in 32 bits.So it should be
ULONG_MAXnow (malloc and all the address code was changed to use unsigned long instead of unsigned int since the patch was written).And
dt_xlateneeds the same information. Its is using a hardcoded 64 bit constant to provide the a simiar check.Quoted 20 lines
Quoted 20 lines
arch/powerpc/boot/types.h +1
-0+#define min (x,y) ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \Index:
kernel/arch/powerpc/boot/devtree.c
===================================================================
---kernel.orig/arch/powerpc/boot/devtree.c2007-09-17
22:12:47.000000000 -0500
+++kernel/arch/powerpc/boot/devtree.c2007-09-17 22:12:51.000000000
-0500arch/powerpc/boot/devtree.c +1
-0@@ -1,6 +1,7 @@/* * devtree.c - convenience functions for device tree manipulation * Copyright 2007 David Gibson, IBM Corporation. +* Copyright 2007 Milton Miller, IBM Corporation. * Copyright (c) 2007 Freescale Semiconductor, Inc. * * Authors: David Gibson <[email protected]> @@ -333,3 +334,68 @@ int dt_is_compatible(void *node, const cQuoted 16 lines
Quoted 6 lines
arch/powerpc/boot/devtree.c +3
-0return 0 ; } + +/** +* dt_find_initrd - set loader initrd location based on existing properties
Quoted 8 lines
+ *
+ * finds the linux,initrd-start and linux,initrd-end properties in
+ * the /chosen node and sets the loader initrd fields accordingly.
+ *
+ * Use this if your loader sets the properties to allow other code to
+ * relocate the tree and/or cause r3 and r4 to be set on true OF
+ * platforms.I am unable to make sense of the paragraph above.
The phrase "relocate the tree" should be "relocate the initrd", which the wrapper will do if it located below vmlinux.size. Also, r3 and r4 need to be set when booting the kernel from a client interface with an initrd so it can take it into consideration when choosing the location to build the flat tree.
Quoted 8 lines
How about:
Filling in the loader info allows
main.cto be aware of the initrd, meaningprep_initrdwill move the initrd if it will be overwritten when the kernel is copied to its runtime location. In addition, if you are booting the kernel from a client interface instead of a flat device tree, this also causes r3 and r4 to be set so the kernel can avoid overwriting the initrd when creating the flat tree.
Quoted 4 lines
Clearer, but I still don't see that it says anything useful - "finds the initrd from the devtree and does all the things that are supposed to be done with an initrd" - which is implied in the previous paragraph.
I was tring to point out there is additional processing that is done when the bootwrapper is aware of the initrd, as opposed to the kernel finding it after it processes the flattened the tree. suggestions?
Quoted 11 lines
Quoted 11 lines
Quoted 10 lines
arch/powerpc/boot/devtree.c int dt_is_compatible(void *node, const c · line 354
Quoted 8 lines
+ */
arch/powerpc/boot/devtree.c +7
-0+void dt_find_initrd (void ) +{ +int rc; +unsigned long long initrd_start, initrd_end; +void *devp; +static const char start_prop[] ="linux,initrd-start" ; +static const char end_prop[] ="linux,initrd-end" ;I think these constants are more obscuring than useful.
Quoted 7 lines
Quoted 4 lines
They are useful to the extent they reduce the number of source characters causing about 8 less line wraps. Since they are used multiple places, the compiler only needs to emit one copy of this byte sequence. Admitedly you made this point in a prior review.
The compiler is perfectly capable of folding identical string constants.
Yes it is, but are you going to leave the constant strings as %s in the printf strings?
Maybe i shold create a function that takes the property and returns the int if its either 32 or 64 bits, calling it twice?
Quoted 28 lines
Quoted 28 lines
Quoted 7 lines
arch/powerpc/boot/devtree.c int dt_is_compatible(void *node, const c · line 359
Quoted 5 lines
arch/powerpc/boot/devtree.c +5
-0+ + devp =finddevice ("/chosen" ); +if (! devp) { +return ; + }CodingStyle would not put { } here.
Yea, nit. not sure why I have the braces there, I usually follow that one. And what's that space doing after !?
Quoted 16 lines
Quoted 12 lines
(quoted diff) +2
-0+ + rc = getprop(devp, start_prop, &initrd_start,
sizeof(initrd_start));arch/powerpc/boot/devtree.c +8
-0+if (rc <0 ) +return ;/* not found */ +/* The properties had to be 8 bytes until 2.6.22 */ +if (rc ==sizeof (unsigned long )) { +unsigned long tmp; +memcpy (&tmp, &initrd_start, rc); + initrd_start = tmp; + }else if (rc !=sizeof (initrd_start)) {/* now they Quoted 1 line
can be 4 */
Right. 8 bytes and 4 bytes, so you should be using explicit length types instead of long and long long.
Quoted 4 lines
Quoted 2 lines
Ok, I guess we ahve u32 and u64 in
types.hnow. But there is other code in the wrapper that assumes its compiled 32 bit ILP.Yes, but that's no reason to propagate the sin.
HAH! so abvoe you are tring to get me to hard code in 32 bits, and now you argue that long == 32 bits is "sinful"?
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ printf("unexpected length of %s in /chosen!\n\r", start_prop); + return;All these
printf()/ return stanzas add a lot of verbosity to this function. Any way they can be consolidated a bit, maybe a single error path that just prints the property values, so the user can figure out what was wrong with them.
Quoted 7 lines
Quoted 4 lines
On a prior review I got asked to split the reasons for ingoring the values below (the > 32 bit address from end < start cases). Admitedly without all the detailed errors the justification for the string varables is reduced.
Hrm. Well, I can't say I'm entirely convinced either way on this one. I guess I'll think about it again once the rest is cleaned up.
I'll make some of these changes when I get back to work (been at the power.org conference), but I still think ulong_max is the correct check.
milton
PATCH 2/15 boot: record header bytes in gunzip_start
In reply to Milton MillerRecord the number of header bytes skipped in the total bytes read field.
This is needed for the initramfs parsing code to find the end of the zip file.
---
Identical to 12169
arch/powerpc/boot/gunzip_util.c +1 -0
@@ -78,6 +78,7 @@ void gunzip_start(struct gunzip_state *sfatal ("inflateInit2 returned %d\n\r" , r); } + state->s.total_in = hdrlen; state->s.next_in = src + hdrlen; state->s.avail_in = srclen - hdrlen; }
Re: [PATCH 2/15] boot: record header bytes in gunzip_start
Quoted 7 lines · Milton Miller
Record the number of header bytes skipped in the total bytes read field.
This is needed for the initramfs parsing code to find the end of the zip file.
Signed-off-by Milton Miller <[email protected]>
Signature · 4 lines
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/~dgibson
PATCH 3/15 boot: simplfy gunzip_finish
In reply to Milton MillerCall gunzip_partial to calculate the remaining length and copy the data to the user buffer. This makes it shorter and reduces duplication.
---
identical content to 12170, removed extra space in change log
arch/powerpc/boot/gunzip_util.c +2 -5
@@ -194,13 +194,10 @@ int gunzip_finish(struct gunzip_state *s {int len; + len =gunzip_partial (state, dst, dstlen); +if (state->s.workspace) { - len =gunzip_partial (state, dst, dstlen);zlib_inflateEnd (&state->s); - }else { -/* uncompressed image */ - len =min (state->s.avail_in, (unsigned )dstlen); -memcpy (dst, state->s.next_in, len); }return len;
PATCH 4/15 bootwrapper: smp support code
In reply to Milton MillerSupport code to move cpus around, both a spin loop and c code to move the cpus before uncompressing and copying the kernel to 0.
The low level code is designed to be included in a crt0 or other assembly file because it may need to be at a fixed location or there may be other entry point requirements.
Note: this code works with kernel head_64.S. head_6xx.S needs the0x60 entry point (it currently mentions something at address 0xC0; but the similar code is at 0xC4); the other heads don't appear to support SMP.
---
vs 12171
get barrier from io.h instead of adding to reg.h
rediff ops.h, Makefile
arch/powerpc/boot/marshal_low.S new file +103 -0
@@ -0,0 +1,103 @@ +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2007 IBM Corporation. + * + * Authors: Milton Miller <[email protected]> + * + */ + +#include "ppc_asm.h" + + .text + /* + * This code is designed to be a kexec entry point block. + * That is, it has both code for the master cpu that begins + * at offset 0 as linked into the image, and a sequence of + * 0x100 bytes that, when copied to address 0, forms the + * wait loop for slave cpus. Each slave should have its + * unique hardware cpu identifier in r3 before entering + * this code. + */ + .globl master +master: b _zimage_start_plat + + .global slave_wait +slave_wait: + /* r3 cpu id, r4 slaves_wait, r5 cpu bit, r6 cpu mask word offset */ + + /* set our bit in the slaves mask */ +98: lwarx r7,r4,r6 + or r8,r7,r5 + stwcx. r8,r4,r6 + bne 98b + + and. r8,r7,r5 + bnel- err_slave + +99: lwz r7,gohere-slave_wait(r4) + cmpwi 0,r7,0 + beq 99b + mtctr r7 + mr r4,r7 + bctr + + + .global gohere +gohere: .long 0 /* when set the slave moves */ + + +err_slave: + stw r5,slave_error-slave_wait(4) /* no locking */ + blr + + .globl slave_error /* set when slave detects error */ +slave_error: + .long 0 + + /* + * The slaves may be in 32 or 64 bit mode, we don't care + * r3 is the slave cpu number, matching the device tree. + */ + .org master+0x60 + .globl slave +slave: bl 1f +1: mflr r4 + addi r4,r4,slave_wait-1b /* code assumes r4=slave_wait */ + li r5,1 + rlwnm r5,r5,r3,0,31 /* bit within word */ + rlwinm r6,r3,32-5+2,4,29 /* word in array */ + addi r6,r6,slaves-slave_wait /* relative to r4, slave_wait */ + b slave_wait + + .org master+0x80 /* put locked bitmask data in another line */ + .global slaves +slaves: + + .globl slaves_end; +slaves_end = 0f + +#if 0 + /* today, the 32 bit kernel starts slaves at 0xc0 + * but this limits us to cpu to 512 vs 1024 + */ + .org master+0xc0 +0: b slave +#endif + + + .org master+0x100 /* we must fit in 0x100 bytes */ +0: +
arch/powerpc/boot/marshal.c new file +276 -0
276 lines not on this page · raw message
arch/powerpc/boot/Makefile +1 -0
@@ -42,6 +42,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util. $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ + marshal.c \ ns16550.c serial.c simple_alloc.c div64.S util.S \ gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
arch/powerpc/boot/reg.h +4 -0
@@ -19,4 +19,8 @@ static inline u32 mfpvr(void) registervoid *__stack_pointer asm("r1" );#define get_sp () (__stack_pointer) +#define HMT_MEDIUM asm volatile("or 2,2,2") +#define HMT_LOW asm volatile("or 1,1,1") + +#endif /* _PPC_BOOT_REG_H */
arch/powerpc/boot/ops.h +8 -1
@@ -18,6 +18,7 @@#define COMMAND_LINE_SIZE 512#define MAX_PATH_LEN 256#define MAX_PROP_LEN 256/* What should this be? */ +#define SMP_SLAVE_SIZE 256/* Size of SMP slave block, kexec/kernel */ typedef void (*kernel_entry_t )(unsigned long r3,unsigned long r4,void *r5);
@@ -86,7 +87,13 @@ int mpsc_console_init(void *devp, structint cpm_console_init (void *devp,struct serial_console_data *scdp);void *simple_alloc_init (char *base,unsigned long heap_size,unsigned long granularity,unsigned long max_allocs); -extern void flush_cache (void *,unsigned long ); +void flush_cache (void *,unsigned long ); +void move_slaves_up (void ); +void move_slaves_here (void *where); +void send_slaves_to_kernel (void *vmlinux_addr); +void slaves_are_low (void ); +void wait_slaves_moved (void ); +int dt_xlate_reg (void *node,int res,unsigned long *addr,unsigned long *size);int dt_xlate_addr (void *node,u32 *buf,int buflen,unsigned long *xlated_addr);int dt_is_compatible (void *node,const char *compat);
PATCH 5/15 bootwrapper: occuppied memory ranges
In reply to Milton MillerAdd a set of library routines to manage gross memory allocations.
This code uses an array in bss to store upto 32 entrys with merging representing a range of memory below rma_end (aka end of real mode memory at 0).
To use this code, a platform would set rma_end (find_rma_end), mark memory ranges occupied (add_known_ranges et al), initialize malloc in the spaces between (ranges_init_malloc), and optionally use the supplied vmlinux_alloc may be used.
---
vs 12172
rename rmo_end to rma_end (real mode area, as used in papr) removed section labels (now in ops.h)
rediff ops.h, Makefile
moved find_rma_end here (from kexec.c in a later patch) find_rma_end searches by node type for "memory", checks that
the parent is the root node, then looks for a reg property with the first address/size pair starting at 0.
arch/powerpc/boot/memranges.c new file +299 -0
@@ -0,0 +1,299 @@ +/* +* 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; either version 2 of the License, or +* (at your option) any later version. +* +* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* Copyright IBM Corporation 2007 +* +* Authors: Milton Miller <[email protected]> +*/ + +#include "ops.h" +#include "stdio.h" +#include "flatdevtree.h" +#include "page.h" +#include "types.h" + +void *rma_end; + +static struct { +void *start, *end; +} ranges[32 ]; +static int num_ranges; + +/** +* find_rma_end - find end of Real Mode Area +* Query the device tree to find the node of type memory that contains a +* reg starting with address 0, and update rma_end to point to the end +* of that region. On PAPR systems, only this RMA region is accessable +* in real mode. +*/ +void find_rma_end (void ) +{ +unsigned int na, ns, reg[4 ], *rp;char path[MAX_PATH_LEN ]; +void *devp, *root;int rc; + + path[0 ] ='\0' ; + root =finddevice ("/" ); +if (!root) +fatal ("Ack, can't get device-tree root" ); + rc =getprop (root,"#address-cells" , &na,sizeof (na)); +if (rc !=sizeof (na)) +fatal ("Ack, no #address-cells in root" ); + rc =getprop (root,"#size-cells" , &ns,sizeof (ns)); +if (rc !=sizeof (ns)) +fatal ("Ack, no #size-cells in root" ); +if (!na || !ns || na <1 || na >2 || ns <1 || ns >2 ) +fatal ("find_rma_end: / #addr-cells or #size-cells unsupported" ); + + devp =NULL ; +while ((devp =find_node_by_devtype (devp,"memory" ))) { +if (root !=get_parent (devp)) { +printf ("Ignoring memory node %s" +" --- not a child of root\n\r" , +get_path (devp, path,sizeof (path))); +continue ; + } + rc =getprop (devp,"reg" , reg,sizeof (reg)); +if (rc < (na + ns) *sizeof (int )) { +printf ("No valid reg property in memory node %s\n\r" , +get_path (devp, path,sizeof (path))); +continue ; + } +/* find the node where the first reg entry starts at 0 */ + rp = ®[0 ]; +if (*rp++) +continue ; +if (na >1 && *rp++) +continue ; + +/* if >4G, limit it */ +if (ns >1 && *rp++) { + rma_end = (void *)0xFFFFFFFF ; +return ; + } + +/* other wise use its size */ + rma_end = (void *)*rp; +return ; + } +fatal ("find_rma_end: didn't find memory at 0\n\r" ); +} + +/** +* add_occupied_range - mark a range as occupied +* @start: start of range pointer +* @end: end of range pointer +* +* Mark the range from @start to @end as occupied. +* Ignore anything above rma_end. +*/ +void add_occupied_range (void *start,void *end) +{ +int i, j; + +if (start == end) +return ; +if (start > rma_end) +return ; +if (end > rma_end) + end = rma_end; +if (start > end) +fatal ("%s: BUG: start %p > end %p\n\r" , __FUNCTION__, + start, end); + +printf ("add %p %p: " , start, end); + +for (i=0 ; i < num_ranges; i++) +if (start <= ranges[i].end) +break ; + +/* extend and merge any overlapping ranges */ +if (i < num_ranges && end >= ranges[i].start) { + ranges[i].start =min (start, ranges[i].start); +for (j=i; j < num_ranges; j++) +if (end >= ranges[j].start) + end =max (end, ranges[j].end); +else +break ; + ranges[i].end = end; + +if (j == i +1 ) { +printf ("extending range %d to %p %p\n\r" , i, + ranges[i].start, ranges[i].end); + }else { +printf ("merged ranges %d to %d now %p %p\n\r" , i, j, + ranges[i].start, ranges[i].end); + + ++i; +memmove (&ranges[i], &ranges[j], + (num_ranges - j) *sizeof (ranges[0 ])); + num_ranges -= j-i; + } + }else { +/* insert a new range */ +if (num_ranges >=ARRAY_SIZE (ranges) -1 ) +fatal ("Too many memory ranges to track\n" ); + +printf ("inserting range %d between %p and %p\n\r" , + i, i ? ranges[i-1 ].end :0 , + i == num_ranges ? rma_end : ranges[i].start); + +memmove (&ranges[i+1 ], &ranges[i], + (num_ranges - i) *sizeof (ranges[0 ])); + num_ranges++; + + ranges[i].start = start; + ranges[i].end = end; + } +} + +/** +* add_occupied_range_ulong - mark a range as occupied +* @start: start of block to occupy +* @end: start of block to occupy +* +* Call add_occupied_range() after casting to ulong @start and @end to +* void * pointers. +*/ +void add_occupied_range_ulong (unsigned long start,unsigned long end) +{ +add_occupied_range ((void *)start, (void *)end); +} + +/** +* add_known_ranges - occupy some known regions +* @dt_blob: a flattend device tree to occupy, or NULL to skip +* +* call add_occupied_range() for the wrapper, loader supplied initrd, +* and, if not %NULL, the device tree blob @dt_blob and any reserved +* memory ranges therein. +*/ +void add_known_ranges (struct boot_param_header *dt_blob) +{ +unsigned long long rstart, rlen, rend, *rsrv; + +add_occupied_range (_start, _end); + +add_occupied_range_ulong (loader_info.initrd_addr, + loader_info.initrd_addr + loader_info.initrd_size); + +if (dt_blob ==NULL ) +return ; + +add_occupied_range (dt_blob, (void *)dt_blob + dt_blob->totalsize); + +/* only support 8-byte reserve map. Only care about < 4G */ + rsrv = (void *)dt_blob + dt_blob->off_mem_rsvmap; +do { + rstart = *rsrv++; + rlen = *rsrv++; + rend = rstart + rlen; + +if (rlen && rstart <UINT_MAX ) { +if (rend <UINT_MAX ) +add_occupied_range_ulong (rstart, rend); +else +add_occupied_range_ulong (rstart,UINT_MAX ); + } + }while (rlen); +} + +/** +* ranges_init_malloc - initialize malloc heap in a free memory range. +* +* Call simple_alloc_init using the largest gap between occupied ranges. +* Does not consider before the first or after the last range. +*/ +void ranges_init_malloc (void ) +{ +int i; +unsigned long size =0 ; +void *heap_start, *heap_end; + +/* +* Allow the beginning for the kernel and the end for +* other things the platform might want to have reserved. +*/ + + heap_start =NULL ;/* avoid gcc warning */ +for (i=1 ; i < num_ranges; i++) { +unsigned long newsize; + + newsize = ranges[i].start - ranges[i-1 ].end; +if (newsize > size) { + size = newsize; + heap_start = ranges[i-1 ].end; + } + } + +if (size <4 *1024 *1024 ) +fatal ("Can't find a sutiable gap (largest 0x%lx)" , size); + +printf ("putting heap between %p and %p size 0x%lx\n\r" , heap_start, + heap_start + size, size); + heap_end =simple_alloc_init (heap_start, size *7 /8 , +PAGE_SIZE ,/* max num alloc */ 4096 ); +if (heap_end > (heap_start + size)) +fatal ("heap alloc overflowed gap (%p)\n\r" , heap_end); + +add_occupied_range (heap_start, heap_end); +} + +/** +* ranges_vmlinux_alloc - an optonal kernel allocator. +* @size: the image size of the kernel +* +* Searches for a location to put the kernel, then reserve that range +* and the area to which the kernel will relocate itself. First try +* address %0. If that is blocked by a previos call to add_occupied_range(), +* try malloc(). If that also fails search for free space between the +* occupied ranges or between the last range and rma_end. +*/ +void *ranges_vmlinux_alloc (unsigned long size) +{ +void *addr; +int i; + +/* Assume _start to _end is occupied */ + addr = (void *)0 ; +if (addr + size < ranges[0 ].start) + goto occupy; + + addr =malloc (size); +if (addr) + goto out; + +for (i=1 ; i < num_ranges; i++) { +if (size < ranges[i].start - ranges[i-1 ].end) + goto occupy_range; + } +if (size < rma_end - ranges[i-1 ].end) + goto occupy_range; + +fatal ("Unable to find a 0x%lx byte gap for the kernel\n" , size); + +occupy_range: + addr = ranges[i-1 ].end; +occupy: +add_occupied_range (addr, addr + size); +out: +/* +* Assume the kernel will decompress to 0, but don't implicity +* create a new gap below the current first range. +*/ +if ((unsigned long )ranges[0 ].end < size) +add_occupied_range_ulong (0 , size); + +return addr; +}
arch/powerpc/boot/ops.h +11 -0
@@ -22,6 +22,8 @@typedef void (*kernel_entry_t )(unsigned long r3,unsigned long r4,void *r5); +struct boot_param_header ; +/* Platform specific operations */ struct platform_ops {void (*fixups)(void );
@@ -99,6 +101,15 @@ int dt_xlate_addr(void *node, u32 *buf,int dt_is_compatible (void *node,const char *compat);void dt_get_reg_format (void *node,u32 *naddr,u32 *nsize); +/* memory ranges */ +extern void *rma_end; +void add_occupied_range (void *start,void *end); +void add_occupied_range_ulong (unsigned long start,unsigned long end); +void add_known_ranges (struct boot_param_header *dt_blob); +void find_rma_end (void ); +void ranges_init_malloc (void ); +void *ranges_vmlinux_alloc (unsigned long size); +static inline void *finddevice (const char *name) {return (dt_ops.finddevice) ? dt_ops.finddevice (name) :NULL ;
arch/powerpc/boot/Makefile +1 -1
@@ -42,7 +42,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util. $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ - marshal.c \ + marshal.c memranges.c \ ns16550.c serial.c simple_alloc.c div64.S util.S \ gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
Re: [PATCH 5/15] bootwrapper: occuppied memory ranges
Quoted 12 lines · Milton Miller
Add a set of library routines to manage gross memory allocations.
This code uses an array in bss to store upto 32 entrys with merging representing a range of memory below
rma_end(aka end of real mode memory at 0).To use this code, a platform would set
rma_end(find_rma_end), mark memory ranges occupied (add_known_rangeset al), initialize malloc in the spaces between (ranges_init_malloc), and optionally use the suppliedvmlinux_allocmay be used.Signed-off-by Milton Miller <[email protected]>
Quoted 9 lines
---
vs 12172
renamermo_endtorma_end(real mode area, as used in papr) removed section labels (now inops.h)
rediffops.h,Makefile
movedfind_rma_endhere (fromkexec.cin a later patch)find_rma_endsearches by node type for "memory", checks that
the parent is the root node, then looks for a reg property with the first address/size pair starting at 0.
Urg. It's an awful lot of code for the bootwrapper. Am I right in understanding that the only reason to use the ranges code is for the ranges based malloc() and vmlinux_alloc() you get out of it?
Signature · 4 lines
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/~dgibson
Re: [PATCH 5/15] bootwrapper: occuppied memory ranges
Quoted 7 lines · David Gibson
Quoted 6 lines · Milton Miller
Add a set of library routines to manage gross memory allocations.
This code uses an array in bss to store upto 32 entrys with merging representing a range of memory below
rma_end(aka end of real mode memory at 0).
Quoted 8 lines
Quoted 4 lines
To use this code, a platform would set
rma_end(find_rma_end), mark memory ranges occupied (add_known_rangeset al), initialize malloc in the spaces between (ranges_init_malloc), and optionally use the suppliedvmlinux_allocmay be used.Urg. It's an awful lot of code for the bootwrapper. Am I right in understanding that the only reason to use the ranges code is for the ranges based
malloc()andvmlinux_alloc()you get out of it?
Yes.
The ranges based malloc is simple_alloc after finding a sutable chunk to operate in.
When doing a kexec, there are several chunks of memory to avoid. There are at least the wrapper, the initrd, the input device tree, and possibly rtas and tce tables. The last two are avoided by parsing the memory resrve list in the flat tree blob.
In practice, on 64 bit powerpc kexec-tools loads the kernel (in this case zImage) immediately following the old kernel _end (becauset the kernel doesnt' allow otherwise, like 32 bit and most other platforms do). If the kernel being execd is larger than the kernel invoking kexec, then the vmlinux will not fit below the wrapper, but when they are the same it will fit. So in the malloc region we need space for random temps, the final device tree, the kernel, and possibly the initrd -- especially if its attached to the zImage instead of supplied by kexec-tools.
While I titled this platform kexec, in reality, it is a generic chain looading platform for flat device trees in that it is invoked with the same calling conveintions as it calls the kernel. With the current policy of run-where-loadeed, the wrapper has to be able to find out what memory is available. It may be above or below itself, and the bulk of available memory may be after any of the above mentioned ranges. The only information is the the flat device tree and its knowledge of itself. Most of this code deals with building the sorted list of what memory is used.
Actually, there is a hole in that malloc may be initialzed below the vmlinux.size and the initrd and deviece tree could end up overwritten. This can't be eliminated without doing something like prpmc2800 where the kernel decompression is started and the elf header is read before initializing malloc. In practice has not triggered because the vmlinux will be malloced before the device tree without an initrd, and with it the kernel is likely smaller than the wrapper (since the memory chunk at 0 is avoided, it requires the end of some other chunk to be low in memory).
At one point you had mentioned considering changes to run out of bss and handling the initrd and kernel with calls to memmove; any such movement would requrie similar information to what is being built into the storted structure in this code to support externally loaded initrds and device-trees, which could not be allocated into the bss wihout arbitrarilly limiting their size.
I've made several changes to the split btween memranges.c and kexec.c over time. Perhaps there are more left. There is a bit of policy in the ranges malloc initialilzation; that could probably be eliminated by query functions for the largest chunk. The vmlinux alloc could try just 0 and malloc(). And the area from the last occupied range to roa_end should be available for malloc as well as the kernel.
milton
PATCH 6/15 bootwrapper: help for 64 bit cpus
In reply to Milton MillerAdd code to check if the processor is in 64 or 32 bit mode using only instructions from the 32 bit subset. If the processor is in 64 bit mode, switch to 32 bit mode by clearing MSR[SF].
Also add a 64 bit procedure descriptor to use as a elf64 entry point.
---
vs 12173
correct comment (equal vs not-equal)
arch/powerpc/boot/crt0.S +36 -0
@@ -17,11 +17,47 @@ _zimage_start_opd: .long _zimage_start, 0, 0, 0 + /* a procedure descriptor used when pretending to be elf64_powerpc */ + .balign 8 + .globl _zimage_start_64 +_zimage_start_64: + .long 0, _zimage_start /* big endian, supported reloc ppc32 */ + .long 0, 0, 0, 0, 0, 0 + + .weak _zimage_start .globl _zimage_start _zimage_start: .globl _zimage_start_lib _zimage_start_lib: + /* Check if the processor is running in 32 bit mode, using + * only 32 bit instructions which should be safe on 32 and + * 64 bit processors. + * + * Subtract bottom 32 bits of MSR from full value recording + * the result. Since MSR[SF] is in the high word, we will + * be equal iff in 32 bit mode (either the processor is + * a 32 bit processor or MSR[SF] = 0). + */ + mfmsr r0 /* grab whole msr */ + rlwinm r8,r0,0,0,31 /* extract bottom word */ + subf. r8,r8,r0 /* subtract, same? */ + beq 0f /* yes: we are 32 bit mode */ + + /* We are in 64-bit mode. This program must run in 32 bit + * mode. Assume we are actually running somewhere in the + * low 32 bits of the address space, so we can just turn + * off MSR[SF] which is bit 0. + */ + .machine push + .machine "ppc64" + rldicl r0,r0,0,1 + sync + mtmsrd r0 + isync + .machine pop +0: /* We are now in 32-bit mode */ + /* Work out the offset between the address we were linked at and the address where we're running. */ bl 1f
Re: [PATCH 6/15] bootwrapper: help for 64 bit cpus
Quoted 17 lines · Milton Miller
Add code to check if the processor is in 64 or 32 bit mode using only instructions from the 32 bit subset. If the processor is in 64 bit mode, switch to 32 bit mode by clearing MSR[SF].
Also add a 64 bit procedure descriptor to use as a elf64 entry point.
Signed-off-by Milton Miller <[email protected]>---
vs 12173
correct comment (equal vs not-equal)Index:
kernel/arch/powerpc/boot/crt0.S
===================================================================
arch/powerpc/boot/crt0.S line 23
Quoted 7 lines
arch/powerpc/boot/crt0.S +4
-0@@ -17,11 +17,47 @@ _zimage_start_opd: .long _zimage_start, 0, 0, 0 + /* a procedure descriptor used when pretending to be elf64_powerpc */ + .balign 8 + .globl _zimage_start_64 +_zimage_start_64:
Hrm, I'd prefer _zimage_start_opd64 in analogy with the COFF opd entry above.
Quoted 45 lines
arch/powerpc/boot/crt0.S +32
-0+ .long 0, _zimage_start /* big endian, supported reloc ppc32 */ + .long 0, 0, 0, 0, 0, 0 + + .weak _zimage_start .globl _zimage_start _zimage_start: .globl _zimage_start_lib _zimage_start_lib: + /* Check if the processor is running in 32 bit mode, using + * only 32 bit instructions which should be safe on 32 and + * 64 bit processors. + * + * Subtract bottom 32 bits of MSR from full value recording + * the result. Since MSR[SF] is in the high word, we will + * be equal iff in 32 bit mode (either the processor is + * a 32 bit processor or MSR[SF] = 0). + */ + mfmsr r0 /* grab whole msr */ + rlwinm r8,r0,0,0,31 /* extract bottom word */ + subf. r8,r8,r0 /* subtract, same? */ + beq 0f /* yes: we are 32 bit mode */ + + /* We are in 64-bit mode. This program must run in 32 bit + * mode. Assume we are actually running somewhere in the + * low 32 bits of the address space, so we can just turn + * off MSR[SF] which is bit 0. + */ + .machine push + .machine "ppc64" + rldicl r0,r0,0,1 + sync + mtmsrd r0 + isync + .machine pop +0: /* We are now in 32-bit mode */ + /* Work out the offset between the address we were linked at and the address where we're running. */ bl 1f_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-dev
Signature · 4 lines
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/~dgibson
PATCH 7/15 bootwrapper: Add kexec callable zImage wrapper
In reply to Milton MillerThis code creates a 32 bit zImage wrapper for a 32 or 64 bit PowerPC Linux kernel. This allows you to kexec a zImage with its compressed vmlinux instead of the uncompressed vmlinux elf. The code is also packaged as a 64 bit elf for use by kexec-tools on 64 bit kernels.
Limitations:
Note: the device-tree generated by kexec-tools is currently version 2, not the version 16 supported by the boot code base.
---find_rmo_end moved to memranges as find_rma_end. early_scan_flat_tree replaced with calls to its pieces in kexec_platform_init
rediff wrapper, Makefile, ops.h
arch/powerpc/boot/kexec.c new file +122 -0
@@ -0,0 +1,122 @@ +/* +* 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; either version 2 of the License, or +* (at your option) any later version. +* +* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* Copyright IBM Corporation 2007 +* +* Authors: Milton Miller <[email protected]> +*/ + +#include "ops.h" +#include "stdio.h" +#include "flatdevtree.h" +#include "page.h" +#include "types.h" + +extern char _start[]; +extern char _end[]; + +BSS_STACK (16 *1024 ); + +static void find_console_from_tree (void ) +{ +int rc =-1 ; + +if (rc) { +/* no console, oh well */ + } +} + +/** +* setup_initial_heap - setup a small heap in the bss +* Using a preallocated heap, setup for scanning the device tree. +* Intended for the initial read while the tree will remain read-only so +* a minimal malloc and search limit can be used. This way we don't have +* lots of data or bss to clear. +*/ +static void setup_initial_heap (void ) +{ +static char initial_heap[8 *1024 ]; +void *heap_end; + + heap_end =simple_alloc_init (initial_heap, +sizeof (initial_heap) *7 /8 , +sizeof (long ),64 ); + +if (heap_end -sizeof (initial_heap) > (void *)&initial_heap[0 ]) +fatal ("Initial heap too big\n\r" ); +} + +static void init_flat_tree (struct boot_param_header *dt_blob) +{ +int rc; + + rc =ft_init (dt_blob, dt_blob->totalsize,/* max_finddevice */ 1024 ); +if (rc) +fatal ("Unable to initialize device_tree library!\n\r" ); +} + +static void *saved_vmlinux_addr; + +static void *kexec_vmlinux_alloc (unsigned long size) +{ +void *addr; + + addr =ranges_vmlinux_alloc (size); + + saved_vmlinux_addr = addr; +return addr; +} + +static void kexec_fixups (void ) +{ +wait_slaves_moved (); +} + +static unsigned long (*finalize_chain)(void ); + +static unsigned long kexec_finalize (void ) +{ +send_slaves_to_kernel (saved_vmlinux_addr); + +return finalize_chain (); +} + +void kexec_platform_init (struct boot_param_header *dt_blob) +{ +slaves_are_low (); +move_slaves_up (); + +setup_initial_heap (); +init_flat_tree (dt_blob); +/* +* drivers can malloc and read the tree, but not realloc later +* or modify the tree now. +*/ +if (!console_ops.write) +find_console_from_tree (); + +find_rma_end (); +dt_find_initrd (); +add_known_ranges (dt_blob); +ranges_init_malloc (); + +/* now that we have a malloc region, start over from the flat tree */ +init_flat_tree (dt_blob); + + platform_ops.vmlinux_alloc = kexec_vmlinux_alloc; + platform_ops.fixups = kexec_fixups; + finalize_chain = dt_ops.finalize; + dt_ops.finalize = kexec_finalize; +}
arch/powerpc/boot/crt0_kexec.S new file +45 -0
45 lines not on this page · raw message
arch/powerpc/boot/wrapper +9 -0
@@ -133,6 +133,12 @@ coff) platformo=$object/of.o lds=$object/zImage.coff.lds ;; +kexec) + platformo=$object/crt0_kexec.o + ;; +kexec64) + platformo="-e _zimage_start_64 $object/crt0_kexec.o" + ;; miboot|uboot) # miboot and U-boot want just the bare bits, not an ELF binary ext=bin
@@ -190,6 +196,9 @@ uboot) fi exit 0 ;; +kexec64) + ${CROSS}objcopy -O elf64-powerpc $ofile + ;; esac addsec() {
arch/powerpc/boot/Makefile +8 -4
@@ -42,12 +42,12 @@ $(addprefix $(obj)/,$(zlib) gunzip_util. $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ - marshal.c memranges.c \ + marshal.c memranges.c kexec.c \ ns16550.c serial.c simple_alloc.c div64.S util.S \ gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \ cpm-serial.c stdlib.c -src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \ +src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c crt0_kexec.S \ cuboot-ebony.c treeboot-ebony.c prpmc2800.c \ ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \ cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c cuboot-bamboo.c
@@ -128,6 +128,9 @@ quiet_cmd_wrap = WRAP $@ cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \ $(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux +kexec-$(CONFIG_PPC32) += zImage.kexec +kexec-$(CONFIG_PPC64) += zImage.kexec64 + image-$(CONFIG_PPC_PSERIES) += zImage.pseries image-$(CONFIG_PPC_MAPLE) += zImage.pseries image-$(CONFIG_PPC_IBM_CELL_BLADE) += zImage.pseries
@@ -140,6 +143,7 @@ image-$(CONFIG_PPC_HOLLY) += zImage.hol image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800 image-$(CONFIG_PPC_ISERIES) += zImage.iseries image-$(CONFIG_DEFAULT_UIMAGE) += uImage +image-$(CONFIG_KEXEC) += $(kexec-y) ifneq ($(CONFIG_DEVICE_TREE),"") image-$(CONFIG_PPC_8xx) += cuImage.8xx
@@ -158,7 +162,7 @@ ifeq ($(CONFIG_PPC32),y) image-$(CONFIG_PPC_PMAC) += zImage.coff zImage.miboot endif -initrd- := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-)) +initrd- := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-) $(kexec-)) initrd-y := $(patsubst zImage%, zImage.initrd%, \ $(patsubst treeImage%, treeImage.initrd%, $(image-y))) initrd-y := $(filter-out $(image-y), $(initrd-y))
@@ -227,7 +231,7 @@ install: $(CONFIGURE) $(addprefix $(obj) # anything not in $(targets) clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \ - otheros.bld + otheros.bld $(kexec-) # clean up files cached by wrapper clean-kernel := vmlinux.strip vmlinux.bin
arch/powerpc/boot/ops.h +1 -0
@@ -95,6 +95,7 @@ void move_slaves_here(void *where);void send_slaves_to_kernel (void *vmlinux_addr);void slaves_are_low (void );void wait_slaves_moved (void ); +void kexec_platform_init (struct boot_param_header *dt_blob);int dt_xlate_reg (void *node,int res,unsigned long *addr,unsigned long *size);int dt_xlate_addr (void *node,u32 *buf,int buflen,unsigned long *xlated_addr);
Re: [PATCH 7/15] bootwrapper: Add kexec callable zImage wrapper
Quoted 40 lines · Milton Miller
This code creates a 32 bit zImage wrapper for a 32 or 64 bit PowerPC Linux kernel. This allows you to kexec a zImage with its compressed vmlinux instead of the uncompressed vmlinux elf. The code is also packaged as a 64 bit elf for use by kexec-tools on 64 bit kernels.
Limitations:
Note: the device-tree generated by kexec-tools is currently version 2, not the version 16 supported by the boot code base.Signed-off-by Milton Miller <[email protected]>---
find_rmo_endmoved to memranges asfind_rma_end.early_scan_flat_treereplaced with calls to its pieces inkexec_platform_init
rediff wrapper,Makefile,ops.hIndex:
kernel/arch/powerpc/boot/kexec.c
===================================================================arch/powerpc/boot/kexec.c new file +18
-0@@ -0,0 +1,122 @@ +/* +* 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; either version 2 of the License, or +* (at your option) any later version. +* +* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* Copyright IBM Corporation 2007 +* +* Authors: Milton Miller <[email protected]>
arch/powerpc/boot/kexec.c line 28
Quoted 10 lines
arch/powerpc/boot/kexec.c new file +10
-0+*/ + +#include "ops.h" +#include "stdio.h" +#include "flatdevtree.h" +#include "page.h" +#include "types.h" + +extern char _start[]; +extern char _end[];
Don't need these externs any more, they're in the headers.
arch/powerpc/boot/kexec.c line 38
Quoted 10 lines
arch/powerpc/boot/kexec.c new file +10
-0+ +BSS_STACK (16 *1024 ); + +static void find_console_from_tree (void ) +{ +int rc =-1 ; + +if (rc) { +/* no console, oh well */ + }
Um... pointless function...?
Quoted 43 lines
arch/powerpc/boot/kexec.c new file +43
-0+} + +/** +* setup_initial_heap - setup a small heap in the bss +* Using a preallocated heap, setup for scanning the device tree. +* Intended for the initial read while the tree will remain read-only so +* a minimal malloc and search limit can be used. This way we don't have +* lots of data or bss to clear. +*/ +static void setup_initial_heap (void ) +{ +static char initial_heap[8 *1024 ]; +void *heap_end; + + heap_end =simple_alloc_init (initial_heap, +sizeof (initial_heap) *7 /8 , +sizeof (long ),64 ); + +if (heap_end -sizeof (initial_heap) > (void *)&initial_heap[0 ]) +fatal ("Initial heap too big\n\r" ); +} + +static void init_flat_tree (struct boot_param_header *dt_blob) +{ +int rc; + + rc =ft_init (dt_blob, dt_blob->totalsize,/* max_finddevice */ 1024 ); +if (rc) +fatal ("Unable to initialize device_tree library!\n\r" ); +} + +static void *saved_vmlinux_addr; + +static void *kexec_vmlinux_alloc (unsigned long size) +{ +void *addr; + + addr =ranges_vmlinux_alloc (size); + + saved_vmlinux_addr = addr; +return addr; +} +
arch/powerpc/boot/kexec.c line 91
Quoted 10 lines
arch/powerpc/boot/kexec.c new file +10
-0+static void kexec_fixups (void ) +{ +wait_slaves_moved (); +} + +static unsigned long (*finalize_chain)(void ); + +static unsigned long kexec_finalize (void ) +{ +send_slaves_to_kernel (saved_vmlinux_addr);
Ow, yuck, no. The finalize callback is for finalizing the device tree, don't abuse it for SMP entry. It's a new thing that needs to be done, so create a new callback for it.
Quoted 86 lines
arch/powerpc/boot/kexec.c new file +31
-0+ +return finalize_chain (); +} + +void kexec_platform_init (struct boot_param_header *dt_blob) +{ +slaves_are_low (); +move_slaves_up (); + +setup_initial_heap (); +init_flat_tree (dt_blob); +/* +* drivers can malloc and read the tree, but not realloc later +* or modify the tree now. +*/ +if (!console_ops.write) +find_console_from_tree (); + +find_rma_end (); +dt_find_initrd (); +add_known_ranges (dt_blob); +ranges_init_malloc (); + +/* now that we have a malloc region, start over from the flat tree */ +init_flat_tree (dt_blob); + + platform_ops.vmlinux_alloc = kexec_vmlinux_alloc; + platform_ops.fixups = kexec_fixups; + finalize_chain = dt_ops.finalize; + dt_ops.finalize = kexec_finalize; +}Index:
kernel/arch/powerpc/boot/crt0_kexec.S
===================================================================arch/powerpc/boot/crt0_kexec.S new file +45
-0@@ -0,0 +1,45 @@ +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2007 IBM Corporation. + * + * Authors: Milton Miller <[email protected]> + * + */ + /* + * The kernel calls out to the first image with + * r3 = boot cpu, r4 = entrypoint, r5 = 0 + * + * kexec-tools purgatory calls this as it would a linux kernel: + * r3 = boot block, r4 = entrypoint, r5 = 0 + * + * The boot block boot_cpu field has been filled in. + * + * kexec-tools and its purgatory are suppposed to copy SMP_SLAVE_SIZE + * bytes from the from entry point, but aparently instead it copies + * from the image start. + */ + .globl _zimage_start +_zimage_start: + +#include "marshal_low.S" + + .globl _zimage_start_plat +_zimage_start_plat: + b _zimage_start_lib + + .globl platform_init +platform_init: + b kexec_platform_initIndex:
kernel/arch/powerpc/boot/wrapper
===================================================================
arch/powerpc/boot/wrapper coff) · line 140
Quoted 8 lines
arch/powerpc/boot/wrapper +5
-0@@ -133,6 +133,12 @@ coff) platformo=$object/of.o lds=$object/zImage.coff.lds ;; +kexec) + platformo=$object/crt0_kexec.o + ;; +kexec64) + platformo="-e _zimage_start_64 $object/crt0_kexec.o"
Arg. Again, just because it happens to fit is not a good reason to abuse platformo - which, obviously enough, s meant to contain the .o file for the platform - to also contain flags.
Quoted 74 lines
arch/powerpc/boot/wrapper +4
-0+ ;; miboot|uboot) # miboot and U-boot want just the bare bits, not an ELF binary ext=bin@@ -190,6 +196,9 @@ uboot) fi exit 0 ;; +kexec64) + ${CROSS}objcopy -O elf64-powerpc $ofile + ;; esac addsec() {Index:
kernel/arch/powerpc/boot/Makefile
===================================================================arch/powerpc/boot/Makefile +8
-4@@ -42,12 +42,12 @@ $(addprefix $(obj)/,$(zlib) gunzip_util. $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ - marshal.c memranges.c \ + marshal.c memranges.c kexec.c \ ns16550.c serial.c simple_alloc.c div64.S util.S \ gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \ cpm-serial.c stdlib.c -src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \ +src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c crt0_kexec.S \ cuboot-ebony.c treeboot-ebony.c prpmc2800.c \ ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \ cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c cuboot-bamboo.c@@ -128,6 +128,9 @@ quiet_cmd_wrap = WRAP $@ cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \ $(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux +kexec-$(CONFIG_PPC32) += zImage.kexec +kexec-$(CONFIG_PPC64) += zImage.kexec64 + image-$(CONFIG_PPC_PSERIES) += zImage.pseries image-$(CONFIG_PPC_MAPLE) += zImage.pseries image-$(CONFIG_PPC_IBM_CELL_BLADE) += zImage.pseries@@ -140,6 +143,7 @@ image-$(CONFIG_PPC_HOLLY) += zImage.hol image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800 image-$(CONFIG_PPC_ISERIES) += zImage.iseries image-$(CONFIG_DEFAULT_UIMAGE) += uImage +image-$(CONFIG_KEXEC) += $(kexec-y) ifneq ($(CONFIG_DEVICE_TREE),"") image-$(CONFIG_PPC_8xx) += cuImage.8xx@@ -158,7 +162,7 @@ ifeq ($(CONFIG_PPC32),y) image-$(CONFIG_PPC_PMAC) += zImage.coff zImage.miboot endif -initrd- := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-)) +initrd- := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-) $(kexec-)) initrd-y := $(patsubst zImage%, zImage.initrd%, \ $(patsubst treeImage%, treeImage.initrd%, $(image-y))) initrd-y := $(filter-out $(image-y), $(initrd-y))@@ -227,7 +231,7 @@ install: $(CONFIGURE) $(addprefix $(obj) # anything not in $(targets) clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \ - otheros.bld + otheros.bld $(kexec-) # clean up files cached by wrapper clean-kernel := vmlinux.strip vmlinux.binIndex:
kernel/arch/powerpc/boot/ops.h
===================================================================
arch/powerpc/boot/ops.h void move_slaves_here(void *where); · line 98
Quoted 4 lines
arch/powerpc/boot/ops.h +1
-0@@ -95,6 +95,7 @@ void move_slaves_here(void *where);void send_slaves_to_kernel (void *vmlinux_addr);void slaves_are_low (void );void wait_slaves_moved (void ); +void kexec_platform_init (struct boot_param_header *dt_blob);
This platform specific function should not poluute ops.h.
Quoted 8 lines
arch/powerpc/boot/ops.h +0
-0int dt_xlate_reg (void *node,int res,unsigned long *addr,unsigned long *size);int dt_xlate_addr (void *node,u32 *buf,int buflen,unsigned long *xlated_addr);_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-dev
Signature · 4 lines
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/~dgibson
PATCH 8/15 bootwrapper: convert flatdevtree to version 16
In reply to Milton Millerkexec-tools still produces a version 2 device tree, while the libraries in the wrapper only support version 16 and later.
Add a routine to convert a v2 flat device tree to a v16 one inplace by inserting OF_DT_NOP and chomping full path. Make space for new headers by moving and then chomping the OF_DT_NOPs.
---
vs 12175
Rediffed Makefile, ops, kexec.c
arch/powerpc/boot/flatdevtree_conv.c new file +280 -0
@@ -0,0 +1,280 @@ +/* +* 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; either version 2 of the License, or +* (at your option) any later version. +* +* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* Copyright IBM Corporation 2007 +* +* Authors: Milton Miller <[email protected]> +*/ +#include "flatdevtree.h" +#include "stdio.h" +#include "ops.h" + +#define MIN_VERSION 2 +#define OUT_VERSION 16 +#define OUT_COMPAT 16 + +#ifdef NO_CHECK +static int check_v123_tree (u32 *start,u32 *limit) +{ +return 0 ; +} +#else +/** +* check_v123_tree - check integrety of a version 1, 2, or 3 tree +* @start: the start of the device tree struct +* @limit: the end of the region for the struct +* structural checks on device_tree +*/ +static int check_v123_tree (u32 *start,u32 *limit) +{ +u32 len; +int depth =0 ; +u32 *dtp = start; + +while (dtp < limit) +switch (*dtp) { +case OF_DT_END : +if (depth) +return -1 ; +return ++dtp - start; +case OF_DT_NOP : + dtp++; +break ; +case OF_DT_END_NODE : + dtp++; + depth--; +break ; +case OF_DT_BEGIN_NODE : + len =strlen ((char *)(++dtp)); +/* check path is suffix to previous? */ + dtp +=1 + (len /4 ); + depth++; +break ; +case OF_DT_PROP : + len = dtp[1 ]; + dtp +=3 ; +if ((len >=8 ) && ((long )dtp &4 )) + dtp++; + dtp += (len +3 ) /4 ; +break ; +default : +return -1 ; + } +return -1 ;/* no OF_DT_END */ +} +#endif + +/** +* nop_to_v16 - add %OF_DT_NOP to hide alignment differences +* @dtp: pointer to the beginning of the struct area to modify +* insert %OF_DT_NOP into the dt_struct @dtp to make it v16 from v1, 2, or 3. +*/ +static int nop_to_v16 (u32 *dtp) +{ +int nops =0 ; +char *p, *s; +int len; +u32 *next; + +while (*dtp !=OF_DT_END ) +switch (*dtp) { +case OF_DT_BEGIN_NODE : +/* v2 & v3 names are full path, v16+ is relative */ + p = (char *)(++dtp); + len =strlen (p); + next = dtp +1 + len /4 ; + +for (s = p + len; *s !='/' ; s--) +if (s == p) +fatal ("name %s has no '/'" , p); + + len -= s++ - p;/* not the slash but the nul */ +memmove (p, s, len); +while (len %4 ) + p[len++] ='\0' ; + dtp += len /4 ; +while (dtp != next) { + *dtp++ =OF_DT_NOP ; + nops++; + } +break ; +case OF_DT_PROP : +/* convert from align_8 to align_4 via prefixing nop */ + len = dtp[1 ]; +if ((len >=8 ) && !((long )dtp &4 )) { +memmove (dtp+1 , dtp,12 ); + *dtp++ =OF_DT_NOP ; + nops++; + } + dtp +=3 + (len +3 )/4 ; +break ; +default : +fatal ("%s: unrecognised tag %d at %p\n" , __FUNCTION__, + *dtp, dtp); +case OF_DT_NOP : + nops ++; +/* fall through */ +case OF_DT_END_NODE : + dtp ++; +break ; + } +return nops; +} + +#if MIN_VERSION <3 ||OUT_VERSION >16 +/** +* move_nops_fwd - move nops in a v16 dt_struct to the beginning +* @start - device tree starting address +* @count - number of %OF_DT_NOP cells to move +*/ +static void move_nops_fwd (u32 *start,int count) +{ +u32 *dtp = start; +int len; +while (count) +switch (*dtp) { +case OF_DT_NOP : +memmove (start+1 ,start,(dtp-start) *4 ); + *start++ =OF_DT_NOP ; + dtp++; + count--; +break ; +case OF_DT_END_NODE : + dtp++; +break ; +case OF_DT_BEGIN_NODE : + len =strlen ((char *)(++dtp)); + dtp +=1 + len /4 ; +break ; +case OF_DT_PROP : + len = dtp[1 ]; + dtp +=3 + (len +3 ) /4 ; +break ; +case OF_DT_END : +fatal ("Not enough nops -- need %d more\n" , count); +return ; +default : + fatal("%s: unknown tag %d at %p", __FUNCTION__, *dtp, dtp) + } +} +#endif + +/** +* conv_flattree_inplace upgrade the version of a boot_param_header +* @tree: pointer to the device tree header to convert +* +* Converts a v1, 2, 3 device tree (of at least MIN_VERSION) +* in place to OUT_VERSION (16) format, usable by flatdevtree.c +*/ +void conv_flattree_inplace (struct boot_param_header *tree) +{ +u32 *dtp; +u32 need =0 , nops; +int slen; + +if (tree->magic !=OF_DT_HEADER ) +fatal ("%s: no magic" , __FUNCTION__); + +if (tree->last_comp_version >3 ) +return ;/* don't know what to do */ + +if (tree->version <MIN_VERSION ) { +printf ("%s: Warning: can't handle version %d tree\n" , + __FUNCTION__, tree->version); +return ; + } + +if (tree->version <2 ) + need++;/* boot_cpu_id */ + +if (tree->version <3 ) + need++;/* dt_string_size */ + +if (OUT_VERSION >16 ) + need++;/* dt_struct_size */ + + dtp = (void *)tree + tree->off_dt_struct; + + slen =check_v123_tree (dtp, (void *)tree + tree->totalsize); +if (slen <0 ) +fatal ("device tree check failed\n" ); + + nops =nop_to_v16 (dtp); + +if (need &1 )/* keep 8 byte alignment of mem reserve */ + need++; + +if (need > nops) +fatal ("Didn't find enough space to add new header fields\n\r" +"(needed %d found %d tree %p)" , need, nops, tree); + +/* ok now compress the dtb struct */ +move_nops_fwd (dtp, need); + dtp += need; + +/* +* move mem_rsvmap and dt_strings if they are before dt_struct +* onto our nops . Adjust start addresses for the 3 sections. +*/ +if ((tree->off_mem_rsvmap < tree->off_dt_struct) || + (tree->off_dt_strings < tree->off_dt_struct)) { +int start, end; +void *ptr; + +if (tree->off_mem_rsvmap < tree->off_dt_strings) + start = tree->off_mem_rsvmap; +else + start = tree->off_dt_strings; + + end = tree->off_dt_struct; + ptr = (void *)tree + start; + +memmove (ptr +4 * need, ptr, end - start); + +if (tree->off_mem_rsvmap < tree->off_dt_struct) + tree->off_mem_rsvmap +=4 * need; +if (tree->off_dt_strings < tree->off_dt_struct) + tree->off_dt_strings +=4 * need; + } + tree->off_dt_struct +=4 * need; + +/* ok now we have space to extend the header. */ +if (tree->version <2 &&MIN_VERSION <2 ) { + tree->boot_cpuid_phys =0 ;/* default, caller can fix */ + } + +/* calculate size of dt_strings_size */ +if (tree->version <3 &&MIN_VERSION <3 ) { +int end = tree->totalsize; + +if (tree->off_dt_strings < tree->off_mem_rsvmap) + end = tree->off_mem_rsvmap; + +if ((tree->off_dt_strings < tree->off_dt_struct) && + (end > tree->off_dt_struct)) + end = tree->off_dt_struct; + + tree->dt_strings_size = end - tree->off_dt_strings; + } + +#if OUT_VERSION >16 + tree->dt_struct_size =4 * slen; +#endif + + tree->version =OUT_VERSION ; + tree->last_comp_version =OUT_COMPAT ; + +return ; +}
arch/powerpc/boot/Makefile +1 -1
@@ -42,7 +42,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util. $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ - marshal.c memranges.c kexec.c \ + flatdevtree_conv.c marshal.c memranges.c kexec.c \ ns16550.c serial.c simple_alloc.c div64.S util.S \ gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
arch/powerpc/boot/ops.h +3 -0
@@ -81,7 +81,10 @@ struct loader_info { };extern struct loader_info loader_info; +struct boot_param_header ; +void start (void ); +void conv_flattree_inplace (struct boot_param_header *tree);int ft_init (void *dt_blob,unsigned int max_size,unsigned int max_find_device);int serial_console_init (void );int ns16550_console_init (void *devp,struct serial_console_data *scdp);
arch/powerpc/boot/kexec.c +1 -0
@@ -99,6 +99,7 @@ void kexec_platform_init(struct boot_parmove_slaves_up ();setup_initial_heap (); +conv_flattree_inplace (dt_blob);init_flat_tree (dt_blob);/* * drivers can malloc and read the tree, but not realloc later
Re: [PATCH 8/15] bootwrapper: convert flatdevtree to version 16
Quoted 32 lines · Milton Miller
kexec-tools still produces a version 2 device tree, while the libraries in the wrapper only support version 16 and later.
Add a routine to convert a v2 flat device tree to a v16 one inplace by inserting
OF_DT_NOPand chomping full path. Make space for new headers by moving and then chomping theOF_DT_NOPs.Signed-off-by Milton Miller <[email protected]>---
vs 12175
RediffedMakefile, ops,kexec.cIndex:
kernel/arch/powerpc/boot/flatdevtree_conv.c
===================================================================arch/powerpc/boot/flatdevtree_conv.c new file +15
-0@@ -0,0 +1,280 @@ +/* +* 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; either version 2 of the License, or +* (at your option) any later version. +* +* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*
arch/powerpc/boot/flatdevtree_conv.c line 25
Quoted 10 lines
arch/powerpc/boot/flatdevtree_conv.c new file +10
-0+* Copyright IBM Corporation 2007 +* +* Authors: Milton Miller <[email protected]> +*/ +#include "flatdevtree.h" +#include "stdio.h" +#include "ops.h" + +#define MIN_VERSION 2 +#define OUT_VERSION 16
Should output version 17. In any case, don't try to be so general - just convert v123 (all basically the same) to latest (i.e. v17) without all the #if nonsense.
Quoted 5 lines
arch/powerpc/boot/flatdevtree_conv.c new file +5
-0+#define OUT_COMPAT 16 + +#ifdef NO_CHECK +static int check_v123_tree (u32 *start,u32 *limit) +{
arch/powerpc/boot/flatdevtree_conv.c line 40
Quoted 10 lines
arch/powerpc/boot/flatdevtree_conv.c new file +10
-0+ return 0; +} +#else +/** +* check_v123_tree - check integrety of a version 1, 2, or 3 tree +* @start: the start of the device tree struct +* @limit: the end of the region for the struct +* structural checks on device_tree +*/ +static int check_v123_tree (u32 *start,u32 *limit)
What is the point of this check? If the device tree is corrupt, we're stuffed anyway, so why bother?
Quoted 92 lines
arch/powerpc/boot/flatdevtree_conv.c new file +92
-0+{ +u32 len; +int depth =0 ; +u32 *dtp = start; + +while (dtp < limit) +switch (*dtp) { +case OF_DT_END : +if (depth) +return -1 ; +return ++dtp - start; +case OF_DT_NOP : + dtp++; +break ; +case OF_DT_END_NODE : + dtp++; + depth--; +break ; +case OF_DT_BEGIN_NODE : + len =strlen ((char *)(++dtp)); +/* check path is suffix to previous? */ + dtp +=1 + (len /4 ); + depth++; +break ; +case OF_DT_PROP : + len = dtp[1 ]; + dtp +=3 ; +if ((len >=8 ) && ((long )dtp &4 )) + dtp++; + dtp += (len +3 ) /4 ; +break ; +default : +return -1 ; + } +return -1 ;/* no OF_DT_END */ +} +#endif + +/** +* nop_to_v16 - add %OF_DT_NOP to hide alignment differences +* @dtp: pointer to the beginning of the struct area to modify +* insert %OF_DT_NOP into the dt_struct @dtp to make it v16 from v1, 2, or 3. +*/ +static int nop_to_v16 (u32 *dtp) +{ +int nops =0 ; +char *p, *s; +int len; +u32 *next; + +while (*dtp !=OF_DT_END ) +switch (*dtp) { +case OF_DT_BEGIN_NODE : +/* v2 & v3 names are full path, v16+ is relative */ + p = (char *)(++dtp); + len =strlen (p); + next = dtp +1 + len /4 ; + +for (s = p + len; *s !='/' ; s--) +if (s == p) +fatal ("name %s has no '/'" , p); + + len -= s++ - p;/* not the slash but the nul */ +memmove (p, s, len); +while (len %4 ) + p[len++] ='\0' ; + dtp += len /4 ; +while (dtp != next) { + *dtp++ =OF_DT_NOP ; + nops++; + } +break ; +case OF_DT_PROP : +/* convert from align_8 to align_4 via prefixing nop */ + len = dtp[1 ]; +if ((len >=8 ) && !((long )dtp &4 )) { +memmove (dtp+1 , dtp,12 ); + *dtp++ =OF_DT_NOP ; + nops++; + } + dtp +=3 + (len +3 )/4 ; +break ; +default : +fatal ("%s: unrecognised tag %d at %p\n" , __FUNCTION__, + *dtp, dtp); +case OF_DT_NOP : + nops ++; +/* fall through */ +case OF_DT_END_NODE : + dtp ++; +break ; + }
arch/powerpc/boot/flatdevtree_conv.c line 142
Quoted 10 lines
arch/powerpc/boot/flatdevtree_conv.c new file +10
-0+return nops; +} + +#if MIN_VERSION <3 ||OUT_VERSION >16 +/** +* move_nops_fwd - move nops in a v16 dt_struct to the beginning +* @start - device tree starting address +* @count - number of %OF_DT_NOP cells to move +*/ +static void move_nops_fwd (u32 *start,int count)
What on earth is the point of this. The NOPs are perfectly valid scattered within the tree, why go to all this trouble to shuffle them about.
Quoted 36 lines
arch/powerpc/boot/flatdevtree_conv.c new file +36
-0+{ +u32 *dtp = start; +int len; +while (count) +switch (*dtp) { +case OF_DT_NOP : +memmove (start+1 ,start,(dtp-start) *4 ); + *start++ =OF_DT_NOP ; + dtp++; + count--; +break ; +case OF_DT_END_NODE : + dtp++; +break ; +case OF_DT_BEGIN_NODE : + len =strlen ((char *)(++dtp)); + dtp +=1 + len /4 ; +break ; +case OF_DT_PROP : + len = dtp[1 ]; + dtp +=3 + (len +3 ) /4 ; +break ; +case OF_DT_END : +fatal ("Not enough nops -- need %d more\n" , count); +return ; +default : + fatal("%s: unknown tag %d at %p", __FUNCTION__, *dtp, dtp) + } +} +#endif + +/** +* conv_flattree_inplace upgrade the version of a boot_param_header +* @tree: pointer to the device tree header to convert +* +* Converts a v1, 2, 3 device tree (of at least MIN_VERSION)
arch/powerpc/boot/flatdevtree_conv.c line 188
Quoted 10 lines
arch/powerpc/boot/flatdevtree_conv.c new file +10
-0+* in place to OUT_VERSION (16) format, usable by flatdevtree.c +*/ +void conv_flattree_inplace (struct boot_param_header *tree) +{ +u32 *dtp; +u32 need =0 , nops; +int slen; + +if (tree->magic !=OF_DT_HEADER ) +fatal ("%s: no magic" , __FUNCTION__);
More pointless tests...
arch/powerpc/boot/flatdevtree_conv.c line 191
Quoted 2 lines
arch/powerpc/boot/flatdevtree_conv.c new file +2
-0+if (tree->last_comp_version >3 ) +return ;/* don't know what to do */
Rather, don't need to do anything.
Quoted 29 lines
arch/powerpc/boot/flatdevtree_conv.c new file +29
-0+ +if (tree->version <MIN_VERSION ) { +printf ("%s: Warning: can't handle version %d tree\n" , + __FUNCTION__, tree->version); +return ; + } + +if (tree->version <2 ) + need++;/* boot_cpu_id */ + +if (tree->version <3 ) + need++;/* dt_string_size */ + +if (OUT_VERSION >16 ) + need++;/* dt_struct_size */ + + dtp = (void *)tree + tree->off_dt_struct; + + slen =check_v123_tree (dtp, (void *)tree + tree->totalsize); +if (slen <0 ) +fatal ("device tree check failed\n" ); + + nops =nop_to_v16 (dtp); + +if (need &1 )/* keep 8 byte alignment of mem reserve */ + need++; + +if (need > nops) + fatal("Didn't find enough space to add new header fields\n\r"
arch/powerpc/boot/flatdevtree_conv.c line 230
Quoted 10 lines
arch/powerpc/boot/flatdevtree_conv.c new file +10
-0+ "(needed %d found %d tree %p)", need, nops, tree); + +/* ok now compress the dtb struct */ +move_nops_fwd (dtp, need); + dtp += need; + +/* +* move mem_rsvmap and dt_strings if they are before dt_struct +* onto our nops . Adjust start addresses for the 3 sections. +*/
Hrm. Do we really need to worry about this case. You may be producing v2 trees in kexec-tools, but do they actually have the blocks out of order? dtc certainly never produced them that way.
Quoted 95 lines
arch/powerpc/boot/flatdevtree_conv.c new file +50
-0+if ((tree->off_mem_rsvmap < tree->off_dt_struct) || + (tree->off_dt_strings < tree->off_dt_struct)) { +int start, end; +void *ptr; + +if (tree->off_mem_rsvmap < tree->off_dt_strings) + start = tree->off_mem_rsvmap; +else + start = tree->off_dt_strings; + + end = tree->off_dt_struct; + ptr = (void *)tree + start; + +memmove (ptr +4 * need, ptr, end - start); + +if (tree->off_mem_rsvmap < tree->off_dt_struct) + tree->off_mem_rsvmap +=4 * need; +if (tree->off_dt_strings < tree->off_dt_struct) + tree->off_dt_strings +=4 * need; + } + tree->off_dt_struct +=4 * need; + +/* ok now we have space to extend the header. */ +if (tree->version <2 &&MIN_VERSION <2 ) { + tree->boot_cpuid_phys =0 ;/* default, caller can fix */ + } + +/* calculate size of dt_strings_size */ +if (tree->version <3 &&MIN_VERSION <3 ) { +int end = tree->totalsize; + +if (tree->off_dt_strings < tree->off_mem_rsvmap) + end = tree->off_mem_rsvmap; + +if ((tree->off_dt_strings < tree->off_dt_struct) && + (end > tree->off_dt_struct)) + end = tree->off_dt_struct; + + tree->dt_strings_size = end - tree->off_dt_strings; + } + +#if OUT_VERSION >16 + tree->dt_struct_size =4 * slen; +#endif + + tree->version =OUT_VERSION ; + tree->last_comp_version =OUT_COMPAT ; + +return ; +}Index:
kernel/arch/powerpc/boot/Makefile
===================================================================arch/powerpc/boot/Makefile +1
-1@@ -42,7 +42,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util. $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ - marshal.c memranges.c kexec.c \ + flatdevtree_conv.c marshal.c memranges.c kexec.c \ ns16550.c serial.c simple_alloc.c div64.S util.S \ gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \Index:
kernel/arch/powerpc/boot/ops.h
===================================================================arch/powerpc/boot/ops.h +3
-0@@ -81,7 +81,10 @@ struct loader_info { };extern struct loader_info loader_info; +struct boot_param_header ; +void start (void ); +void conv_flattree_inplace (struct boot_param_header *tree);int ft_init (void *dt_blob,unsigned int max_size,unsigned int max_find_device);int serial_console_init (void );int ns16550_console_init (void *devp,struct serial_console_data *scdp);Index:
kernel/arch/powerpc/boot/kexec.c
===================================================================arch/powerpc/boot/kexec.c +1
-0@@ -99,6 +99,7 @@ void kexec_platform_init(struct boot_parmove_slaves_up ();setup_initial_heap (); +conv_flattree_inplace (dt_blob);init_flat_tree (dt_blob);/* * drivers can malloc and read the tree, but not realloc later _______________________________________________
Linuxppc-dev mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-dev
Signature · 4 lines
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/~dgibson
Re: [PATCH 8/15] bootwrapper: convert flatdevtree to version 16
Quoted 43 lines · David Gibson
Quoted 42 lines · Milton Miller
kexec-tools still produces a version 2 device tree, while the libraries in the wrapper only support version 16 and later.
Add a routine to convert a v2 flat device tree to a v16 one inplace by inserting
OF_DT_NOPand chomping full path. Make space for new headers by moving and then chomping theOF_DT_NOPs.Signed-off-by Milton Miller <[email protected]>---
vs 12175
RediffedMakefile, ops,kexec.cIndex:
kernel/arch/powerpc/boot/flatdevtree_conv.c
===================================================================arch/powerpc/boot/flatdevtree_conv.c new file +0
-017:49:04.000000000 -0500
arch/powerpc/boot/flatdevtree_conv.c new file +2
-0@@ -0,0 +1,280 @@ +/* +* 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corporation 2007
+ *
+ * Authors: Milton Miller <[email protected]>
+ */arch/powerpc/boot/flatdevtree_conv.c new file +2
-0+#include "flatdevtree.h" +#include "stdio.h"
Quoted 8 lines
arch/powerpc/boot/flatdevtree_conv.c line 25
Quoted 4 lines
arch/powerpc/boot/flatdevtree_conv.c new file +4
-0+#include "ops.h" + +#define MIN_VERSION 2 +#define OUT_VERSION 16Should output version 17. In any case, don't try to be so general - just convert v123 (all basically the same) to latest (i.e. v17) without all the #if nonsense.
Outputing v17 instead of 16 requires more words to be added to the header, and the library does fine with v16. Actually the v1 trees has some other differences such as initrd addresses were kernel linear not real, cpus were assigned logical numbers ... so while the structure didn't change except for the header field, the contents did. Actually, when converting v3 to v16 some of the code issn't needed, the ifs allow the code size to be reduced.
Quoted 11 lines
Quoted 11 lines
arch/powerpc/boot/flatdevtree_conv.c new file +10
-0+#define OUT_COMPAT 16 + +#ifdef NO_CHECK +static int check_v123_tree (u32 *start,u32 *limit) +{ +return 0 ; +} +#else +/** +* check_v123_tree - check integrety of a version 1, 2, or 3 tree
Quoted 8 lines
Quoted 5 lines
+ * @start: the start of the device tree struct
+ * @limit: the end of the region for the struct
+ * structural checks ondevice_tree
+ */
+static intcheck_v123_tree(u32 *start, u32 *limit)What is the point of this check? If the device tree is corrupt, we're stuffed anyway, so why bother?
Hence the ifdef NO_CHECK. When developing, sometimes its nice to know if its your input or your program. These functions are destructive to an improperlly formed tree, and in non-obvious ways. When debugging, it's not hard to hardcode console write or read the printf string buffer with a hardware debugger to see error messages. That said, it could be removed.
Quoted 100 lines
Quoted 100 lines
arch/powerpc/boot/flatdevtree_conv.c new file +42
-0+{ +u32 len; +int depth =0 ; +u32 *dtp = start; + +while (dtp < limit) +switch (*dtp) { +case OF_DT_END : +if (depth) +return -1 ; +return ++dtp - start; +case OF_DT_NOP : + dtp++; +break ; +case OF_DT_END_NODE : + dtp++; + depth--; +break ; +case OF_DT_BEGIN_NODE : + len =strlen ((char *)(++dtp)); +/* check path is suffix to previous? */ + dtp +=1 + (len /4 ); + depth++; +break ; +case OF_DT_PROP : + len = dtp[1 ]; + dtp +=3 ; +if ((len >=8 ) && ((long )dtp &4 )) + dtp++; + dtp += (len +3 ) /4 ; +break ; +default : +return -1 ; + } +return -1 ;/* no OF_DT_END */ +} +#endif + +/** +* nop_to_v16 - add %OF_DT_NOP to hide alignment differences +* @dtp: pointer to the beginning of the struct area to modify +* insert %OF_DT_NOP into the dt_struct @dtp to make it v16 from v1, 2, or 3.
+ */arch/powerpc/boot/flatdevtree_conv.c new file +55
-0+static int nop_to_v16 (u32 *dtp) +{ +int nops =0 ; +char *p, *s; +int len; +u32 *next; + +while (*dtp !=OF_DT_END ) +switch (*dtp) { +case OF_DT_BEGIN_NODE : +/* v2 & v3 names are full path, v16+ is relative */ + p = (char *)(++dtp); + len =strlen (p); + next = dtp +1 + len /4 ; + +for (s = p + len; *s !='/' ; s--) +if (s == p) +fatal ("name %s has no '/'" , p); + + len -= s++ - p;/* not the slash but the nul */ +memmove (p, s, len); +while (len %4 ) + p[len++] ='\0' ; + dtp += len /4 ; +while (dtp != next) { + *dtp++ =OF_DT_NOP ; + nops++; + } +break ; +case OF_DT_PROP : +/* convert from align_8 to align_4 via prefixing nop */ + len = dtp[1 ]; +if ((len >=8 ) && !((long )dtp &4 )) { +memmove (dtp+1 , dtp,12 ); + *dtp++ =OF_DT_NOP ; + nops++; + } + dtp +=3 + (len +3 )/4 ; +break ; +default : +fatal ("%s: unrecognised tag %d at %p\n" , __FUNCTION__, + *dtp, dtp); +case OF_DT_NOP : + nops ++; +/* fall through */ +case OF_DT_END_NODE : + dtp ++; +break ; + } +return nops; +} + +#if MIN_VERSION <3 ||OUT_VERSION >16 +/** +* move_nops_fwd - move nops in a v16 dt_struct to the beginning
Quoted 8 lines
Quoted 4 lines
+ * @start - device tree starting address
+ * @count - number of %OF_DT_NOP cells to move
+ */
+static voidmove_nops_fwd(u32 *start, int count)What on earth is the point of this. The NOPs are perfectly valid scattered within the tree, why go to all this trouble to shuffle them about.
And if you notice, there is a "how many to move" argument. The point of moving them to the front of the tree is the v17 device tree header takes more space than the v3 one, and the v2 header is smaller than both v17 and v16 header. Since I am converting the tree in place, the space has to come from somewhere. Since we are pretty much guaranteed to get several nops, this function moves them forward so they can be overwritten. In practice we move 1-3 NOPS from the early properties > 8 bytes and early grandchild nodes (eg /cpus/PowerPC,xxx).
Quoted 41 lines
Quoted 41 lines
arch/powerpc/boot/flatdevtree_conv.c new file +40
-0+{ +u32 *dtp = start; +int len; +while (count) +switch (*dtp) { +case OF_DT_NOP : +memmove (start+1 ,start,(dtp-start) *4 ); + *start++ =OF_DT_NOP ; + dtp++; + count--; +break ; +case OF_DT_END_NODE : + dtp++; +break ; +case OF_DT_BEGIN_NODE : + len =strlen ((char *)(++dtp)); + dtp +=1 + len /4 ; +break ; +case OF_DT_PROP : + len = dtp[1 ]; + dtp +=3 + (len +3 ) /4 ; +break ; +case OF_DT_END : +fatal ("Not enough nops -- need %d more\n" , count); +return ; +default : + fatal("%s: unknown tag %d at %p", __FUNCTION__, *dtp, dtp) + } +} +#endif + +/** +* conv_flattree_inplace upgrade the version of a boot_param_header +* @tree: pointer to the device tree header to convert +* +* Converts a v1, 2, 3 device tree (of at least MIN_VERSION) +* in place to OUT_VERSION (16) format, usable by flatdevtree.c +*/ +void conv_flattree_inplace (struct boot_param_header *tree) +{
Quoted 8 lines
arch/powerpc/boot/flatdevtree_conv.c line 188
Quoted 6 lines
arch/powerpc/boot/flatdevtree_conv.c new file +6
-0+u32 *dtp; +u32 need =0 , nops; +int slen; + +if (tree->magic !=OF_DT_HEADER ) +fatal ("%s: no magic" , __FUNCTION__);More pointless tests...
It says you didn't pass a tree ... yea, its dumb, but I prefer an explicit error to figuring out where a machine check came from.
Quoted 5 lines
arch/powerpc/boot/flatdevtree_conv.c line 191
Quoted 3 lines
arch/powerpc/boot/flatdevtree_conv.c new file +2
-0+if (tree->last_comp_version >3 ) +return ;/* don't know what to do */ Rather, don't need to do anything.
If the tree is >= 16 then we don't presently need to do anything. If there is a theoritical v4 tree we don't know what to do. And if output version is 17 but input is 16 we don't know what to do either, because there likely aren't nops in the tree to consume. I suppose we could preceed it with a check for version == OUTPUT_VERSION, but then I'm sure I'd get pointless differentation :-).
Quoted 36 lines
Quoted 36 lines
arch/powerpc/boot/flatdevtree_conv.c new file +35
-0+ +if (tree->version <MIN_VERSION ) { +printf ("%s: Warning: can't handle version %d tree\n" , + __FUNCTION__, tree->version); +return ; + } + +if (tree->version <2 ) + need++;/* boot_cpu_id */ + +if (tree->version <3 ) + need++;/* dt_string_size */ + +if (OUT_VERSION >16 ) + need++;/* dt_struct_size */ + + dtp = (void *)tree + tree->off_dt_struct; + + slen =check_v123_tree (dtp, (void *)tree + tree->totalsize); +if (slen <0 ) +fatal ("device tree check failed\n" ); + + nops =nop_to_v16 (dtp); + +if (need &1 )/* keep 8 byte alignment of mem reserve */ + need++; + +if (need > nops) +fatal ("Didn't find enough space to add new header fields\n\r" +"(needed %d found %d tree %p)" , need, nops, tree); + +/* ok now compress the dtb struct */ +move_nops_fwd (dtp, need); + dtp += need; +
Quoted 8 lines
arch/powerpc/boot/flatdevtree_conv.c line 230
Quoted 4 lines
arch/powerpc/boot/flatdevtree_conv.c new file +4
-0+/* +* move mem_rsvmap and dt_strings if they are before dt_struct +* onto our nops . Adjust start addresses for the 3 sections. +*/ Hrm. Do we really need to worry about this case. You may be producing v2 trees in kexec-tools, but do they actually have the blocks out of order? dtc certainly never produced them that way.
Out of order? There has never been a spec as to the order of the blocks, only the implicit assumption that they follow the device tree header in a reasonably packed sequence. booting-without-of says it must be in ram,; the offsets are unsigned 32 bit quantities.
As to the order, used, the first implemntation was the kernel which writes memreserve, strings, then struct (both the openfirmware client in prom_init and the iSeries procedural library in dt.c). The second implentation written is a procedural based library (similar to iseries, never published, but still used internally) that starts with a pre-built header and string table, builds the dt_struct as the functions are called, and when finished copies the memreserve table and fills in the dt_size, total size, and memreserve offset.
fs2dt writes memreserve, struct, then strings. Aparently the same as dtc. But yes, the strings can be before the struct, and the mem reserve may or may not be when the strings are before the struct.
Quoted 112 lines
Quoted 105 lines
arch/powerpc/boot/flatdevtree_conv.c new file +50
-0+if ((tree->off_mem_rsvmap < tree->off_dt_struct) || + (tree->off_dt_strings < tree->off_dt_struct)) { +int start, end; +void *ptr; + +if (tree->off_mem_rsvmap < tree->off_dt_strings) + start = tree->off_mem_rsvmap; +else + start = tree->off_dt_strings; + + end = tree->off_dt_struct; + ptr = (void *)tree + start; + +memmove (ptr +4 * need, ptr, end - start); + +if (tree->off_mem_rsvmap < tree->off_dt_struct) + tree->off_mem_rsvmap +=4 * need; +if (tree->off_dt_strings < tree->off_dt_struct) + tree->off_dt_strings +=4 * need; + } + tree->off_dt_struct +=4 * need; + +/* ok now we have space to extend the header. */ +if (tree->version <2 &&MIN_VERSION <2 ) { + tree->boot_cpuid_phys =0 ;/* default, caller can fix */ + } + +/* calculate size of dt_strings_size */ +if (tree->version <3 &&MIN_VERSION <3 ) { +int end = tree->totalsize; + +if (tree->off_dt_strings < tree->off_mem_rsvmap) + end = tree->off_mem_rsvmap; + +if ((tree->off_dt_strings < tree->off_dt_struct) && + (end > tree->off_dt_struct)) + end = tree->off_dt_struct; + + tree->dt_strings_size = end - tree->off_dt_strings; + } + +#if OUT_VERSION >16 + tree->dt_struct_size =4 * slen; +#endif + + tree->version =OUT_VERSION ; + tree->last_comp_version =OUT_COMPAT ; + +return ; +}Index:
kernel/arch/powerpc/boot/Makefile
===================================================================
--- kernel.orig/arch/powerpc/boot/Makefile 2007-09-20
17:42:24.000000000 -0500
+++kernel/arch/powerpc/boot/Makefile2007-09-20 17:49:04.000000000
-0500arch/powerpc/boot/flatdevtree_conv.c new file +1
-1@@ -42,7 +42,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util. $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ - marshal.c memranges.c kexec.c \ + flatdevtree_conv.c marshal.c memranges.c kexec.c \ ns16550.c serial.c simple_alloc.c div64.S util.S \arch/powerpc/boot/flatdevtree_conv.c new file +0
-0gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \Index:
kernel/arch/powerpc/boot/ops.h
===================================================================
---kernel.orig/arch/powerpc/boot/ops.h2007-09-20 17:42:24.000000000
-0500
+++kernel/arch/powerpc/boot/ops.h2007-09-20 17:49:04.000000000 -0500arch/powerpc/boot/flatdevtree_conv.c new file +3
-0@@ -81,7 +81,10 @@ struct loader_info { };extern struct loader_info loader_info; +struct boot_param_header ; +void start (void ); +void conv_flattree_inplace (struct boot_param_header *tree);int ft_init (void *dt_blob,unsigned int max_size,unsigned int max_find_device);int serial_console_init (void );int ns16550_console_init(void *devp, struct
serial_console_data
*scdp);
Index:kernel/arch/powerpc/boot/kexec.c
===================================================================
---kernel.orig/arch/powerpc/boot/kexec.c2007-09-20
17:42:24.000000000 -0500
+++kernel/arch/powerpc/boot/kexec.c2007-09-20 17:49:04.000000000
-0500arch/powerpc/boot/flatdevtree_conv.c new file +1
-0@@ -99,6 +99,7 @@ void kexec_platform_init(struct boot_parmove_slaves_up ();setup_initial_heap (); +conv_flattree_inplace (dt_blob);init_flat_tree (dt_blob);/* * drivers can malloc and read the tree, but not realloc later _______________________________________________
Linuxppc-dev mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-devSignature · 4 lines
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/~dgibson
Re: [PATCH 8/15] bootwrapper: convert flatdevtree to version 16
Quoted 4 lines · Milton Miller
Quoted 1 line · David Gibson
On Fri, Sep 21, 2007 at 06:05:06PM -0500, Milton Miller wrote:
[snip]
Quoted 9 lines
Quoted 6 lines
arch/powerpc/boot/flatdevtree_conv.c line 25
Quoted 2 lines
arch/powerpc/boot/flatdevtree_conv.c new file +2
-0+#define MIN_VERSION 2 +#define OUT_VERSION 16Should output version 17. In any case, don't try to be so general - just convert v123 (all basically the same) to latest (i.e. v17) without all the #if nonsense.
Outputing v17 instead of 16 requires more words to be added to the header, and the library does fine with v16.
For now. libfdt will want v17. Although it will (eventually) have it's own v16->v17 conversion code.
Quoted 4 lines
Actually the v1 trees has
some other differences such as initrd addresses were kernel linear not real, cpus were assigned logical numbers ... so while the structure didn't change except for the header field, the contents did.
!? what's your source for this. v2 and v3 were absolutely supposed to be backwards compatible with v1 which would not be the case with silent semantic changes such as this.
Quoted 3 lines
Actually,
when converting v3 to v16 some of the code issn't needed, the ifs allow the code size to be reduced.
Yes, but it never will be, because the only reason we'd include this file is for converting old kexec-tools device trees which are v2 not v3.
Quoted 19 lines
Quoted 10 lines
Quoted 10 lines
arch/powerpc/boot/flatdevtree_conv.c new file +10
-0+#define OUT_COMPAT 16 + +#ifdef NO_CHECK +static int check_v123_tree (u32 *start,u32 *limit) +{ +return 0 ; +} +#else +/** +* check_v123_tree - check integrety of a version 1, 2, or 3 tree Quoted 8 lines
Quoted 5 lines
+ * @start: the start of the device tree struct
+ * @limit: the end of the region for the struct
+ * structural checks ondevice_tree
+ */
+static intcheck_v123_tree(u32 *start, u32 *limit)What is the point of this check? If the device tree is corrupt, we're stuffed anyway, so why bother?
Quoted 6 lines
Hence the ifdef
NO_CHECK. When developing, sometimes its nice to know
if its your input or your program. These functions are destructive to an improperlly formed tree, and in non-obvious ways. When debugging, it's not hard to hardcode console write or read the printf string buffer with a hardware debugger to see error messages. That said, it could be removed.
Right. Debugging code shouldn't pollute final patches.
[snip]
Quoted 12 lines
Quoted 11 lines
arch/powerpc/boot/flatdevtree_conv.c line 142
Quoted 7 lines
arch/powerpc/boot/flatdevtree_conv.c new file +7
-0+#if MIN_VERSION <3 ||OUT_VERSION >16 +/** +* move_nops_fwd - move nops in a v16 dt_struct to the beginning +* @start - device tree starting address +* @count - number of %OF_DT_NOP cells to move +*/ +static void move_nops_fwd (u32 *start,int count)What on earth is the point of this. The NOPs are perfectly valid scattered within the tree, why go to all this trouble to shuffle them about.
Quoted 8 lines
And if you notice, there is a "how many to move" argument. The point of moving them to the front of the tree is the v17 device tree header takes more space than the v3 one, and the v2 header is smaller than both v17 and v16 header. Since I am converting the tree in place, the space has to come from somewhere. Since we are pretty much guaranteed to get several nops, this function moves them forward so they can be overwritten. In practice we move 1-3 NOPS from the early properties > 8 bytes and early grandchild nodes (eg /cpus/PowerPC,xxx).
This is a hell of a lot of bother to go to for a few bytes. Allocating a big-enough buffer for any reasonable devtree in BSS and memmove()ing into there would be far simpler.
Remember this is a hack for horrid old device trees produced by kexec-tools. It simply doesn't justify large amounts of code to work around.
[snip]
Quoted 11 lines
Quoted 4 lines
arch/powerpc/boot/flatdevtree_conv.c line 191
Quoted 2 lines
arch/powerpc/boot/flatdevtree_conv.c new file +2
-0+if (tree->last_comp_version >3 ) +return ;/* don't know what to do */ Rather, don't need to do anything.
If the tree is >= 16 then we don't presently need to do anything. If
there is a theoritical v4 tree we don't know what to do. And if output version is 17 but input is 16 we don't know what to do either, because there likely aren't nops in the tree to consume. I suppose we could preceed it with a check for version ==OUTPUT_VERSION, but then I'm sure I'd get pointless differentation :-).
There will never be a v4. Or anything between v3 and v16.
Again this is far too general. It's a hack to deal with kexec-tools old trees. Therefore it doesn't need to deal with any general old tree, just the minimum to deal with trees as produced by old kexec-tools.
[snip]
Quoted 14 lines
Quoted 8 lines
arch/powerpc/boot/flatdevtree_conv.c line 230
Quoted 4 lines
arch/powerpc/boot/flatdevtree_conv.c new file +4
-0+/* +* move mem_rsvmap and dt_strings if they are before dt_struct +* onto our nops . Adjust start addresses for the 3 sections. +*/ Hrm. Do we really need to worry about this case. You may be producing v2 trees in kexec-tools, but do they actually have the blocks out of order? dtc certainly never produced them that way.
Out of order? There has never been a spec as to the order of the blocks, only the implicit assumption that they follow the device tree header in a reasonably packed sequence. booting-without-of says it must be in ram,; the offsets are unsigned 32 bit quantities.
Quoted 8 lines
As to the order, used, the first implemntation was the kernel which writes memreserve, strings, then struct (both the openfirmware client in
prom_initand the iSeries procedural library indt.c). The second implentation written is a procedural based library (similar to iseries, never published, but still used internally) that starts with a pre-built header and string table, builds thedt_structas the functions are called, and when finished copies the memreserve table and fills in thedt_size, total size, and memreserve offset.
Hrm. Yes, well, the iSeries tree is weird in a bunch of ways.
Quoted 3 lines
fs2dt writes memreserve, struct, then strings. Aparently the same as dtc. But yes, the strings can be before the struct, and the mem reserve may or may not be when the strings are before the struct.
Again. We don't need to deal with the general case here - just the real case of trees produced by old kexec-tools.
[snip]
Signature · 4 lines
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/~dgibson
Re: [PATCH 8/15] bootwrapper: convert flatdevtree to version 16
Quoted 11 lines · David Gibson
Quoted 2 lines · Milton Miller
Quoted 1 line · David Gibson
On Fri, Sep 21, 2007 at 06:05:06PM -0500, Milton Miller wrote:
[snip]
Quoted 7 lines
Quoted 6 lines
arch/powerpc/boot/flatdevtree_conv.c line 25
Quoted 2 lines
arch/powerpc/boot/flatdevtree_conv.c new file +2
-0+#define MIN_VERSION 2 +#define OUT_VERSION 16Should output version 17. In any case, don't try to be so general - just convert v123 (all basically the same) to latest (i.e. v17) without all the #if nonsense.
Quoted 5 lines
Quoted 2 lines
Outputing v17 instead of 16 requires more words to be added to the header, and the library does fine with v16.
For now. libfdt will want v17. Although it will (eventually) have it's own
v16->v17conversion code.
If libfdt gets merged without supporting v16 input, then that will be a regression. This code isn't pretending to address that. The current flat tree code works with v16.
Quoted 8 lines
Quoted 4 lines
Actually the v1 trees has
some other differences such as initrd addresses were kernel linear not real, cpus were assigned logical numbers ... so while the structure didn't change except for the header field, the contents did.!? what's your source for this. v2 and v3 were absolutely supposed to be backwards compatible with v1 which would not be the case with silent semantic changes such as this.
What's your souce for saying the were supposed to be backwards compatable? That dtc fills out the struct header so?
My source is my involvment when v2 was defined (they were discovered while writing my device tree generation code):
The actual binary structure is compatable, just not the contents of the properties nor how any slave cpus wait (for some trees it doesn't matter).
And some more changes just before that:
So its mostly when the kernel generated and required v1 trees, it was ppc64 only and had these other content and handoff semantics. If it were to get a v1 tree, it only copes for the boot cpu determination I'm not aware of any code other than the kernel that would actually generate a v1 tree (other than dtc, which always supporteed v2, and doesn't care about these differences).
Quoted 27 lines
Quoted 3 lines
Actually,
when converting v3 to v16 some of the code issn't needed, the ifs allow the code size to be reduced.Yes, but it never will be, because the only reason we'd include this file is for converting old kexec-tools device trees which are v2 not v3.
Quoted 19 lines
Quoted 18 lines
Quoted 5 lines
arch/powerpc/boot/flatdevtree_conv.c new file +5
-0+#define OUT_COMPAT 16 + +#ifdef NO_CHECK +static int check_v123_tree (u32 *start,u32 *limit) +{arch/powerpc/boot/flatdevtree_conv.c line 40
Quoted 10 lines
arch/powerpc/boot/flatdevtree_conv.c new file +10
-0+ return 0; +} +#else +/** +* check_v123_tree - check integrety of a version 1, 2, or 3 tree +* @start: the start of the device tree struct +* @limit: the end of the region for the struct +* structural checks on device_tree +*/ +static int check_v123_tree (u32 *start,u32 *limit)What is the point of this check? If the device tree is corrupt, we're stuffed anyway, so why bother?
Quoted 8 lines
Quoted 6 lines
Hence the ifdef
NO_CHECK. When developing, sometimes its nice to know
if its your input or your program. These functions are destructive to an improperlly formed tree, and in non-obvious ways. When debugging, it's not hard to hardcode console write or read the printf string buffer with a hardware debugger to see error messages. That said, it could be removed.Right. Debugging code shouldn't pollute final patches.
There debug code, and validation code. I call this the later. It validates that the information that should be redundant is in fact redundant before its removed. The response of the kernel to the tree may be different if this check fails..
Quoted 22 lines
[snip]
Quoted 12 lines
Quoted 11 lines
arch/powerpc/boot/flatdevtree_conv.c line 142
Quoted 7 lines
arch/powerpc/boot/flatdevtree_conv.c new file +7
-0+#if MIN_VERSION <3 ||OUT_VERSION >16 +/** +* move_nops_fwd - move nops in a v16 dt_struct to the beginning +* @start - device tree starting address +* @count - number of %OF_DT_NOP cells to move +*/ +static void move_nops_fwd (u32 *start,int count)What on earth is the point of this. The NOPs are perfectly valid scattered within the tree, why go to all this trouble to shuffle them about.
Quoted 8 lines
And if you notice, there is a "how many to move" argument. The point of moving them to the front of the tree is the v17 device tree header takes more space than the v3 one, and the v2 header is smaller than both v17 and v16 header. Since I am converting the tree in place, the space has to come from somewhere. Since we are pretty much guaranteed to get several nops, this function moves them forward so they can be overwritten. In practice we move 1-3 NOPS from the early properties > 8 bytes and early grandchild nodes (eg /cpus/PowerPC,xxx).
Quoted 3 lines
This is a hell of a lot of bother to go to for a few bytes. Allocating a big-enough buffer for any reasonable devtree in BSS and memmove()ing into there would be far simpler.
How big is enough? Who is going to do the research for the various firmware levels of the big machines to find out how big the tree is?
Sure there are other ways to get the tree to version 16, one way is to change what is generated. We could update kexec-tools fs2dt to geneerate a v16 tree to support zImages.
A question for the list: does anyone else have firmware/environment that supplies a tree < v16?
Quoted 6 lines
[snip]
Quoted 5 lines
Quoted 4 lines
arch/powerpc/boot/flatdevtree_conv.c line 191
Quoted 2 lines
arch/powerpc/boot/flatdevtree_conv.c new file +2
-0+if (tree->last_comp_version >3 ) +return ;/* don't know what to do */ Rather, don't need to do anything.
Quoted 8 lines
Quoted 6 lines
If the tree is >= 16 then we don't presently need to do anything. If
there is a theoritical v4 tree we don't know what to do. And if output version is 17 but input is 16 we don't know what to do either, because there likely aren't nops in the tree to consume. I suppose we could preceed it with a check for version ==OUTPUT_VERSION, but then I'm sure I'd get pointless differentation :-).There will never be a v4. Or anything between v3 and v16.
I could see a v4 defined as v3 + the extra header in v17, not that I am proposing that. Someone decided to skip to v16 for a reason. If we knew there would never be v4-v15, why did we skip them?
[too general]
Quoted 24 lines
[snip]
Quoted 14 lines
Quoted 8 lines
arch/powerpc/boot/flatdevtree_conv.c line 230
Quoted 4 lines
arch/powerpc/boot/flatdevtree_conv.c new file +4
-0+/* +* move mem_rsvmap and dt_strings if they are before dt_struct +* onto our nops . Adjust start addresses for the 3 sections. +*/ Hrm. Do we really need to worry about this case. You may be producing v2 trees in kexec-tools, but do they actually have the blocks out of order? dtc certainly never produced them that way.
Out of order? There has never been a spec as to the order of the blocks, only the implicit assumption that they follow the device tree header in a reasonably packed sequence. booting-without-of says it must be in ram,; the offsets are unsigned 32 bit quantities.
Quoted 8 lines
As to the order, used, the first implemntation was the kernel which writes memreserve, strings, then struct (both the openfirmware client in
prom_initand the iSeries procedural library indt.c). The second implentation written is a procedural based library (similar to iseries, never published, but still used internally) that starts with a pre-built header and string table, builds thedt_structas the functions are called, and when finished copies the memreserve table and fills in thedt_size, total size, and memreserve offset.
Quoted 1 line
Hrm. Yes, well, the iSeries tree is weird in a bunch of ways.
My point is its the same as the client interface code, and proves the point the order is not specified nor need it be. And since the order is the same in platforms/iseries/dt.c and kernel/prom_init.c, I fail to see your point of calling the iseries code wierd. It's building a device tree via the structured programming methods of calling functions, each of which creates a node and the properties for that node. Doesn't sound that much different than how a ieee bytecode program would create the device tree and fill out properties, and I would expect any firmware who created the device tree from scratch (as oposed to editing a paritially built tree like the fixup hooks presently in the wrapper) would be structured similarly. Since it doesn't ahve a dynamic insertion library, it must fill in all the properties of a node completely before its children, and must travel some depth first order when creating the tree. I don't see any reason to call it wierd.
Quoted 7 lines
Quoted 4 lines
fs2dt writes memreserve, struct, then strings. Aparently the same as dtc. But yes, the strings can be before the struct, and the mem reserve may or may not be when the strings are before the struct.
Again. We don't need to deal with the general case here - just the real case of trees produced by old kexec-tools.
This function isn't conver_kexec_tree_inplacee. While my justification for merging this code is it can be used as the target for kexec with kexec-tools, its not my only use. I also have my internal library that generates a v3 tree with the pieces ordered differently. If the code is changed from its general support to support only the tree generated by kexec-tools, then merging has little benifit to me and in fact it is harder (I have to maintain a diff to a changing target vs adding a file to the makefile).
I'll write a later reply that talks about what subsets of this series make sense to merge.
milton
Re: [PATCH 8/15] bootwrapper: convert flatdevtree to version 16
Quoted 15 lines · Milton Miller
Quoted 14 lines · David Gibson
Quoted 2 lines · Milton Miller
Quoted 1 line · David Gibson
On Fri, Sep 21, 2007 at 06:05:06PM -0500, Milton Miller wrote:
[snip]
Quoted 9 lines
Quoted 6 lines
arch/powerpc/boot/flatdevtree_conv.c line 25
Quoted 2 lines
arch/powerpc/boot/flatdevtree_conv.c new file +2
-0+#define MIN_VERSION 2 +#define OUT_VERSION 16Should output version 17. In any case, don't try to be so general - just convert v123 (all basically the same) to latest (i.e. v17) without all the #if nonsense.
Outputing v17 instead of 16 requires more words to be added to the header, and the library does fine with v16.
Quoted 6 lines
Quoted 2 lines
For now. libfdt will want v17. Although it will (eventually) have it's own
v16->v17conversion code.If libfdt gets merged without supporting v16 input, then that will be a
regression. This code isn't pretending to address that. The current
flat tree code works with v16.
Hrm, true. Since I'm working on merging libfdt right now, I guess that moves up my schedule for getting the v16->v17 conversion code working.
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines
Actually the v1 trees has
some other differences such as initrd addresses were kernel linear not real, cpus were assigned logical numbers ... so while the structure didn't change except for the header field, the contents did.
Quoted 6 lines
Quoted 3 lines
!? what's your source for this. v2 and v3 were absolutely supposed to be backwards compatible with v1 which would not be the case with silent semantic changes such as this.
What's your souce for saying the were supposed to be backwards compatable? That dtc fills out the struct header so?
Sitting next to BenH and knowing he always intended them to be so.
Quoted 10 lines
My source is my involvment when v2 was defined (they were discovered while writing my device tree generation code):
The actual binary structure is compatable, just not the contents of the properties nor how any slave cpus wait (for some trees it doesn't matter).
http://git.kernel.org/?p=linux/kernel/git/horms/kexec-tools-
testing.git;a=blob;f=kexec/arch/ppc64/fs2dt.c;
hb=b84b87747a16f0afbef6f6802bb794a94f4961d9
An old version of fs2dt is hardly definitive. It could just be Plain Wrong, nothing to do with the dt version.
Quoted 6 lines
And some more changes just before that:
http://git.kernel.org/?p=linux/kernel/git/torvalds/old-2.6-bkcvs.git;
a=history;f=arch/ppc64/kernel/prom_init.c;
h=e570799a84cc5328e9f0fd44592cb0b828d8c13a;
hb=4ae24c4e8a8f68950a7774ca1cdfe69bfe4e2ffc
I don't know what bit you're referring to in that batch of commits.
Quoted 6 lines
So its mostly when the kernel generated and required v1 trees, it was ppc64 only and had these other content and handoff semantics. If it were to get a v1 tree, it only copes for the boot cpu determination I'm not aware of any code other than the kernel that would actually generate a v1 tree (other than dtc, which always supporteed v2, and doesn't care about these differences).
Signature · 4 lines
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/~dgibson
Re: [PATCH 8/15] bootwrapper: convert flatdevtree to version 16
Quoted 31 lines · David Gibson
Quoted 14 lines · Milton Miller
Quoted 13 lines · David Gibson
Quoted 2 lines · Milton Miller
Quoted 1 line · David Gibson
On Fri, Sep 21, 2007 at 06:05:06PM -0500, Milton Miller wrote:
[snip]
Quoted 8 lines
Quoted 2 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+#define MIN_VERSION 2 +#define OUT_VERSION 16zActually the v1 trees has
some other differences such as initrd addresses were kernel linear not real, cpus were assigned logical numbers ... so while the structure didn't change except for the header field, the contents did.Quoted 6 lines
Quoted 3 lines
!? what's your source for this. v2 and v3 were absolutely supposed to be backwards compatible with v1 which would not be the case with silent semantic changes such as this.
What's your souce for saying the were supposed to be backwards compatable? That dtc fills out the struct header so?
Sitting next to BenH and knowing he always intended them to be so.
Quoted 7 lines
My source is my involvment when v2 was defined (they were discovered while writing my device tree generation code):
The actual binary structure is compatable, just not the contents of the properties nor how any slave cpus wait (for some trees it doesn't matter).
Quoted 6 lines
Quoted 3 lines
http://git.kernel.org/?p=linux/kernel/git/horms/kexec-tools-
testing.git;a=blob;f=kexec/arch/ppc64/fs2dt.c;
hb=b84b87747a16f0afbef6f6802bb794a94f4961d9An old version of fs2dt is hardly definitive. It could just be Plain Wrong, nothing to do with the dt version.
Sorry, copy and paste error. I was tring to point out this changelog in 2.6.10:
Quoted 9 lines
Quoted 7 lines
And some more changes just before that:
http://git.kernel.org/?p=linux/kernel/git/torvalds/old-2.6-bkcvs.git;
a=history;f=arch/ppc64/kernel/prom_init.c;
h=e570799a84cc5328e9f0fd44592cb0b828d8c13a;
hb=4ae24c4e8a8f68950a7774ca1cdfe69bfe4e2ffcI don't know what bit you're referring to in that batch of commits.
The following properties changed semantics and no heuristics are employed to check for the old vs new:
(1) tces changed from virtual to real
(2) cpus spin on physical (hw id) not logical (0-n)
Other changes in that series
(3) 0->klimit is not a memreserve in the tree (we now allow overlapping reserves, but not at the time)
(4) rtas properties are in a different location (but both could exist)
Quoted 7 lines
Quoted 7 lines
So its mostly when the kernel generated and required v1 trees, it was ppc64 only and had these other content and handoff semantics. If it were to get a v1 tree, it only copes for the boot cpu determination I'm not aware of any code other than the kernel that would actually generate a v1 tree (other than dtc, which always supporteed v2, and doesn't care about these differences).
So trying to boot 2.6.9 (2004-10-18 cutoff) kernel from a tree for 2.6.10 would fail, and vice versa. But a 2.6.10 kernel can boot a v1 tree with properties, memreserves, and cpu ids that it expects, getting the boot-cpuid from the extra property in the tree.
Is that compatible? If you only are talking about parsing the tree it is.
milton
Re: [PATCH 8/15] bootwrapper: convert flatdevtree to version 16
Quoted 2 lines · Milton Miller
On Sep 26, 2007, at 9:45 PM, David Gibson wrote:
[snip]
Quoted 17 lines
Quoted 17 lines
Quoted 2 lines
What's your souce for saying the were supposed to be backwards compatable? That dtc fills out the struct header so?
Sitting next to BenH and knowing he always intended them to be so.
Quoted 11 lines
My source is my involvment when v2 was defined (they were discovered while writing my device tree generation code):
The actual binary structure is compatable, just not the contents of the
properties nor how any slave cpus wait (for some trees it doesn't matter).http://git.kernel.org/?p=linux/kernel/git/horms/kexec-tools-
testing.git;a=blob;f=kexec/arch/ppc64/fs2dt.c;
hb=b84b87747a16f0afbef6f6802bb794a94f4961d9
Quoted 8 lines
Quoted 2 lines
An old version of fs2dt is hardly definitive. It could just be Plain Wrong, nothing to do with the dt version.
Sorry, copy and paste error. I was tring to point out this changelog in 2.6.10:
http://git.kernel.org/?p=linux/kernel/git/torvalds/old-2.6-bkcvs.git;
a=commitdiff;h=e1b47549d1588ccea1fa5726eb430aae4e80f8ed
Hrm, I see, yes that seems conclusive enough. Yuck.
In which case, I think we should try to forget that v1 ever existed. I don't think anyone ever generated v1 trees other than kernels which also consumed them, and I doubt current kernels will correctly deal with v1 trees in this form.
In any case, this is all rather beside the point. My basic point is that this bootwrapper stuff should not attempt to be a general backwards compatibility layer for every broken early dt format that ever existed. In general we should try to make sure nothing ever uses <v16 trees. We want, here, to do the minimum we can get away with to support the specific v2 trees produced by kexec-tools, as an interim measure while kexec-tools itself is fixed to produce v17 trees (say, by replacing fs2dt with dtc plus a libfdt based post-processing program).
Signature · 4 lines
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/~dgibson
Re: [PATCH 8/15] bootwrapper: convert flatdevtree to version 16
Quoted 10 lines · David Gibson
Quoted 9 lines · Milton Miller
Quoted 4 lines · David Gibson
Quoted 4 lines
The actual binary structure is compatable, just not the contents of the
properties nor how any slave cpus wait (for some trees it doesn't matter).Sorry, copy and paste error. I was tring to point out this changelog in 2.6.10:
Quoted 8 lines
Quoted 2 lines
http://git.kernel.org/?p=linux/kernel/git/torvalds/old-2.6-bkcvs.git;
a=commitdiff;h=e1b47549d1588ccea1fa5726eb430aae4e80f8edHrm, I see, yes that seems conclusive enough. Yuck.
In which case, I think we should try to forget that v1 ever existed. I don't think anyone ever generated v1 trees other than kernels which also consumed them,
I believe this to be true, unless you count telling dtc to do so.
Quoted 2 lines
and I doubt current kernels will correctly deal
with v1 trees in this form.
I'm quite certain of that.
Quoted 4 lines
In any case, this is all rather beside the point. My basic point is that this bootwrapper stuff should not attempt to be a general backwards compatibility layer for every broken early dt format that ever existed.
The only broken format was v1; I was submitting v2 :-). Version 16 was "... to support a more compact representation, for use by embedded systems mostly" http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=34153fa3af45d84f3221d9b67ba2ab7e8a220d28
Quoted 4 lines
In general we should try to make sure nothing ever uses <v16 trees. We want, here, to do the minimum we can get away with to support the specific v2 trees produced by kexec-tools, as an interim measure
As I stated, that by itself isn't sufficient for my usage, as I have other v2 trees I need to deal with, at least until that generator gets updated.
Quoted 3 lines
while kexec-tools itself is fixed to produce v17 trees (say, by replacing fs2dt with dtc plus a libfdt based post-processing program).
If you thought there were complaints trying to require an external utility to build zImage, just wait until you try to make kexec-tools not be self-contained. Currently kexec doesn't even use a data directory, instead it builds the purgatory and other trampoline binaries into the kexec program. Incorporating the post-processing and generation using libfdt (with a copy of the library in the source) could fly, if people don't care about kexec into kernels from 2.6.10 to 2.6.14 when v16 was merged (about 1 year).
Actually, there is another approach: put this converter in kexec's purgatory or even the kexec program. It can then run conditionally under command line flags to keep compatibility with the old kernels. If and when its is decided to only support >=v16 in kexec-tools it can be removed and we don't have this interim support code in the kernel forever (I'll handle my other usage out of tree).
milton
Re: [PATCH 8/15] bootwrapper: convert flatdevtree to version 16
On Fri, Sep 28, 2007 at 10:16:51AM -0500, Milton Miller wrote:
[snip]
Quoted 6 lines
Actually, there is another approach: put this converter in kexec's purgatory or even the kexec program. It can then run conditionally under command line flags to keep compatibility with the old kernels. If and when its is decided to only support >=v16 in kexec-tools it can be removed and we don't have this interim support code in the kernel forever (I'll handle my other usage out of tree).
Hurrah! Well, please do that then.
Signature · 4 lines
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/~dgibson
PATCH 9/15 bootwrapper: rtas support
In reply to Milton MillerThis code provides a console write that calls put-term-char.
To avoid PIC relocation of the absolute rtas addresses, hide the actual call to rtas in assembly and declare all variables as int.
An instantiated rtas will be protected by a reserved range in the device tree, so no explicit call to add_occupied_range is needed here.
---
vs 12176rtas_put_term_write now takes const char *buf
rediff ops.h, Makefile
arch/powerpc/boot/rtas.c new file +146 -0
@@ -0,0 +1,146 @@ +/* +* 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; either version 2 of the License, or +* (at your option) any later version. +* +* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* Copyright 2007 IBM Corporation. +* +* Authors: Milton Miller <[email protected]> +* +*/ + +#include "ops.h" +#include "stdio.h" +#include "flatdevtree.h" + +static int rtas_entry; +static int rtas_base; +static int rtas_size; + +static void find_rtas (void ) +{ +int rc; +void *devp; +char *str; + + devp =finddevice ("/rtas" ); +if (! devp) +return ; + + str ="linux,rtas-entry" ; + rc =getprop (devp, str, &rtas_entry,sizeof (rtas_entry)); +if (rc <0 ) +return ; +if (rc !=sizeof (rtas_entry)) + goto fail; + + str ="rtas-size" ; + rc =getprop (devp, str, &rtas_size,sizeof (rtas_size)); +if (rc <0 ) +return ; +if (rc !=sizeof (rtas_size)) + goto fail; + + str ="linux,rtas-base" ; + rc =getprop (devp, str, &rtas_base,sizeof (rtas_base)); +if (rc <0 ) { +printf ("rtas-size but no linux,rtas-base in /rtas. " +"disabling wrapper rtas interface\n\r" ); + rtas_entry =0 ; +return ; + } + +if (rc !=sizeof (rtas_base)) + goto fail; + +return ; + + +fail: +printf ("Unexpected length %d of %s property in /rtas.\n\r" +"disabling wrapper rtas interface\n\r" , rc, str); + rtas_entry =0 ; +return ; +} + +/* +* PIC relocation of function pointers happens at call time. +* We have an absolute out-of-image address. So tell C they +* are just integers, and hide the call as an out-of-file +* function. +*/ +__asm__ ( +" .globl call_rtas\n" +" call_rtas: mtctr 5\n" +" bctr\n" + ); + +void call_rtas (int args[],int base,int entry); + + +static int put_term_char; + +static void rtas_put_term_write (const char *buf,int len) +{ +int i, args[5 ]; + + args[0 ] = put_term_char; + args[1 ] =1 ;/* num inputs */ + args[2 ] =1 ;/* num outputs */ + +for (i=0 ; i < len; ) { + args[3 ] = buf[i]; + args[4 ] =0 ; + +call_rtas (args, rtas_base, rtas_entry); +if (args[4 ] ==0 )/* SUCCESS */ + i++; +else if (args[4 ] ==-1 )/* HARDWARE_ERROR */ +break ; +/* else retry */ + } +} + +int rtas_console_init (void ) +{ +void *devp; +int rc; + + + devp =finddevice ("/rtas" ); +if (!devp) +return -1 ; + +if (!rtas_entry) +find_rtas (); +if (!rtas_entry) +return -1 ; + + rc =getprop (devp,"put-term-char" , &put_term_char, +sizeof (put_term_char)); +if (rc ==sizeof (put_term_char)) + console_ops.write = rtas_put_term_write; +else + put_term_char =-1 ; + +return put_term_char ==-1 ?-1 :0 ; +} + +/* for debug, hard code */ +void use_rtas_console (int entry,int base,int tc) +{ + rtas_entry = entry; + rtas_base = base; + put_term_char = tc; + console_ops.write = rtas_put_term_write; +}
arch/powerpc/boot/ops.h +2 -0
@@ -99,6 +99,8 @@ void send_slaves_to_kernel(void *vmlinuxvoid slaves_are_low (void );void wait_slaves_moved (void );void kexec_platform_init (struct boot_param_header *dt_blob); +int rtas_console_init (void ); +void use_rtas_console (int entry,int base,int tc);int dt_xlate_reg (void *node,int res,unsigned long *addr,unsigned long *size);int dt_xlate_addr (void *node,u32 *buf,int buflen,unsigned long *xlated_addr);
arch/powerpc/boot/kexec.c +3 -0
@@ -33,6 +33,9 @@ static void find_console_from_tree(void) {int rc =-1 ; + rc =rtas_console_init (); +if (!rc) +return ;if (rc) {/* no console, oh well */ }
arch/powerpc/boot/Makefile +1 -1
@@ -42,7 +42,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util. $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ - flatdevtree_conv.c marshal.c memranges.c kexec.c \ + flatdevtree_conv.c marshal.c memranges.c kexec.c rtas.c \ ns16550.c serial.c simple_alloc.c div64.S util.S \ gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
Re: [PATCH 9/15] bootwrapper: rtas support
Quoted 50 lines · Milton Miller
This code provides a console write that calls put-term-char.
To avoid PIC relocation of the absolute rtas addresses, hide the actual call to rtas in assembly and declare all variables as int.
An instantiated rtas will be protected by a reserved range in the device tree, so no explicit call to
add_occupied_rangeis needed here.Signed-off-by Milton Miller <[email protected]>---
vs 12176rtas_put_term_writenow takes const char *buf
rediffops.h,MakefileIndex:
kernel/arch/powerpc/boot/rtas.c
===================================================================arch/powerpc/boot/rtas.c new file +30
-0@@ -0,0 +1,146 @@ +/* +* 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; either version 2 of the License, or +* (at your option) any later version. +* +* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* Copyright 2007 IBM Corporation. +* +* Authors: Milton Miller <[email protected]> +* +*/ + +#include "ops.h" +#include "stdio.h" +#include "flatdevtree.h" + +static int rtas_entry; +static int rtas_base; +static int rtas_size; + +static void find_rtas (void )
arch/powerpc/boot/rtas.c line 40
Quoted 10 lines
arch/powerpc/boot/rtas.c new file +10
-0+{ +int rc; +void *devp; +char *str; + + devp =finddevice ("/rtas" ); +if (! devp) +return ; + + str ="linux,rtas-entry" ;
wtf? Just use the literals in the getprop() calls, this is pure obfuscation.
Quoted 31 lines
arch/powerpc/boot/rtas.c new file +31
-0+ rc =getprop (devp, str, &rtas_entry,sizeof (rtas_entry)); +if (rc <0 ) +return ; +if (rc !=sizeof (rtas_entry)) + goto fail; + + str ="rtas-size" ; + rc =getprop (devp, str, &rtas_size,sizeof (rtas_size)); +if (rc <0 ) +return ; +if (rc !=sizeof (rtas_size)) + goto fail; + + str ="linux,rtas-base" ; + rc =getprop (devp, str, &rtas_base,sizeof (rtas_base)); +if (rc <0 ) { +printf ("rtas-size but no linux,rtas-base in /rtas. " +"disabling wrapper rtas interface\n\r" ); + rtas_entry =0 ; +return ; + } + +if (rc !=sizeof (rtas_base)) + goto fail; + +return ; + + +fail: +printf ("Unexpected length %d of %s property in /rtas.\n\r" +"disabling wrapper rtas interface\n\r" , rc, str);
arch/powerpc/boot/rtas.c line 81
Quoted 10 lines
arch/powerpc/boot/rtas.c new file +10
-0+ rtas_entry =0 ; +return ; +} + +/* +* PIC relocation of function pointers happens at call time. +* We have an absolute out-of-image address. So tell C they +* are just integers, and hide the call as an out-of-file +* function. +*/
I don't get this. If we can call into the kernel using a function pointer, you should be able to call into rtas without this weirdness.
Quoted 110 lines
arch/powerpc/boot/rtas.c new file +65
-0+__asm__ ( +" .globl call_rtas\n" +" call_rtas: mtctr 5\n" +" bctr\n" + ); + +void call_rtas (int args[],int base,int entry); + + +static int put_term_char; + +static void rtas_put_term_write (const char *buf,int len) +{ +int i, args[5 ]; + + args[0 ] = put_term_char; + args[1 ] =1 ;/* num inputs */ + args[2 ] =1 ;/* num outputs */ + +for (i=0 ; i < len; ) { + args[3 ] = buf[i]; + args[4 ] =0 ; + +call_rtas (args, rtas_base, rtas_entry); +if (args[4 ] ==0 )/* SUCCESS */ + i++; +else if (args[4 ] ==-1 )/* HARDWARE_ERROR */ +break ; +/* else retry */ + } +} + +int rtas_console_init (void ) +{ +void *devp; +int rc; + + + devp =finddevice ("/rtas" ); +if (!devp) +return -1 ; + +if (!rtas_entry) +find_rtas (); +if (!rtas_entry) +return -1 ; + + rc =getprop (devp,"put-term-char" , &put_term_char, +sizeof (put_term_char)); +if (rc ==sizeof (put_term_char)) + console_ops.write = rtas_put_term_write; +else + put_term_char =-1 ; + +return put_term_char ==-1 ?-1 :0 ; +} + +/* for debug, hard code */ +void use_rtas_console (int entry,int base,int tc) +{ + rtas_entry = entry; + rtas_base = base; + put_term_char = tc; + console_ops.write = rtas_put_term_write; +}Index:
kernel/arch/powerpc/boot/ops.h
===================================================================arch/powerpc/boot/ops.h +2
-0@@ -99,6 +99,8 @@ void send_slaves_to_kernel(void *vmlinuxvoid slaves_are_low (void );void wait_slaves_moved (void );void kexec_platform_init (struct boot_param_header *dt_blob); +int rtas_console_init (void ); +void use_rtas_console (int entry,int base,int tc);int dt_xlate_reg (void *node,int res,unsigned long *addr,unsigned long *size);int dt_xlate_addr (void *node,u32 *buf,int buflen,unsigned long *xlated_addr);Index:
kernel/arch/powerpc/boot/kexec.c
===================================================================arch/powerpc/boot/kexec.c +3
-0@@ -33,6 +33,9 @@ static void find_console_from_tree(void) {int rc =-1 ; + rc =rtas_console_init (); +if (!rc) +return ;if (rc) {/* no console, oh well */ }Index:
kernel/arch/powerpc/boot/Makefile
===================================================================arch/powerpc/boot/Makefile +1
-1@@ -42,7 +42,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util. $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ - flatdevtree_conv.c marshal.c memranges.c kexec.c \ + flatdevtree_conv.c marshal.c memranges.c kexec.c rtas.c \ ns16550.c serial.c simple_alloc.c div64.S util.S \ gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-dev
Signature · 4 lines
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/~dgibson
PATCH 10/15 bootwrapper: add cpio file extraction library.
In reply to Milton MillerAdd a library to search through a cpio or initramfs buffer for a specified path name. No canocalization of the path is performed.
---
vs 12177
rediff Makefile
cpio.c should be reusable by a stand alone user space applicaton.
arch/powerpc/boot/cpio.c new file +306 -0
@@ -0,0 +1,306 @@ +/* +* 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; either version 2 of the License, or +* (at your option) any later version. +* +* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* Copyright 2007 IBM Corporation. +* +* Authors: Milton Miller <[email protected]> +* +*/ + +#include "cpio.h" +#include "string.h" + +struct cpio_header { +char ino[8 ]; +char mode[8 ]; +char uid[8 ]; +char gid[8 ]; +char nlink[8 ]; +char mtime[8 ]; +char filesize[8 ]; +char maj[8 ]; +char min[8 ]; +char rmaj[8 ]; +char rmin[8 ]; +char namesize[8 ]; +char chksum[8 ]; +} cpio_header_buf; + +static int check_magic (char magic[6 ]) +{ +return !memcmp (magic,"070701" ,6 ) || !memcmp (magic,"070702" ,6 ); +} + +static int read_magic (struct gunzip_state *stream) +{ +int len; +char magic[6 ]; + + len =gunzip_partial (stream, magic,sizeof (magic)); +if (len ==0 ) +return 0 ; + +if (len ==sizeof (magic) &&check_magic (magic)) +return len; + + +/* Not the right magic or short read. We might have stumbled +* onto a compressed archive immediately following an +* uncompressed one, or just some NUL bytes at the end of the +* archive. Inform the higher layers by the negative length. +*/ +return -len; +} + +static int get_cpio_header (struct gunzip_state *stream) +{ +int len; + + len =read_magic (stream); +if (len <=0 ) +return len; + +gunzip_exactly (stream, &cpio_header_buf,sizeof (cpio_header_buf)); + len +=sizeof (cpio_header_buf); + +return len; +} + +static unsigned int cpio_str_to_num (char hexascii[8 ]) +{ +unsigned int num =0 ; +char c; +int d; + +for (d=0 ; d <8 ; d++) { + c = hexascii[d]; + num <<=4 ; +if (c >='0' && c <='9' ) { + num += c -'0' ; + }else if (c >='A' && c <='F' ) { + num += c -'A' +10 ; + }else if (c >='a' && c <='f' ) { + num += c -'a' +10 ; + }else { +cpio_error ("bad cpio archive header: " +"invalid a hex digit" ); + } + } + +return num; +} + +static char name_buf[MAX_PATH +1 ]; +static const char cpio_end[] ="TRAILER!!!" ; +#define CPIO_END_LEN sizeof(cpio_end) + +/* check_next_file +* Look for @path in @stream. Set @consumed to the number of bytes +* succesfully read and processed. return 1 on match, 0 for discarding +* an unmatched file, -1 on end of archive (either detected trailer or +* EOF on stream), or -(1 + bytes read) for a short read or bad magic +* number. (For the short or bad read, the consumed is not changed). +*/ +static int check_next_file (char *path,int pathlen, +struct gunzip_state *stream,int *consumed) +{ +int len, total, match; + +if (pathlen >MAX_PATH ) { +cpio_error ("path too long to search\n" ); + } + total =get_cpio_header (stream); +if (total <=0 ) +return total -1 ; + + len =cpio_str_to_num (cpio_header_buf.namesize); + +if (len == pathlen || len ==CPIO_END_LEN ) { +gunzip_exactly (stream, name_buf, len); + total += len; + match = !strcmp (name_buf, path); +if (!match && !cpio_str_to_num (cpio_header_buf.filesize)) + match = -!strcmp (name_buf, cpio_end); + }else { +gunzip_discard (stream, len); + total += len; + name_buf[0 ] ='\0' ; + match =0 ; + } + + len = total %4 ; +if (len) { +gunzip_discard (stream,4 - len); + total +=4 - len; + } + +if (!match) { + len =cpio_str_to_num (cpio_header_buf.filesize); +gunzip_discard (stream, len); + total += len; + + len = total %4 ; +if (len) { +gunzip_discard (stream,4 - len); + total +=4 - len; + } + } + + *consumed += total; +return match; +} + +static char *this_buf; +static int this_archive; + +/* find_in_cpio. +* find a pathname @path in a single cpio archive described by @stream. +* Return is the same as check_next_file. +*/ +int find_in_cpio (char *path,struct gunzip_state *stream) +{ +int found; +int pathlen =strlen (path) +1 ; + + this_archive =0 ; +do { + found =check_next_file (path, pathlen, stream, &this_archive); + }while (found ==0 ); + +return found; +} + +/* find_in_initramfs +* Search a initramfs buffer for a given path name. Returns 0 on +* not found, or 1 with @state ready to read the file. +* +* Note: this returns the first match, not the last. The kernel +* decompressor effectivly uses the last match. This code also +* doesn't worry about the directories in the path existing. +*/ +int find_in_initramfs (char *path,char *buf,int len, +struct gunzip_state *stream) +{ +int found, total =0 ; +int pathlen =strlen (path) +1 ; +int *ibuf; + +do { +/* get to word boundary, but stop if not NUL */ +for (; total %4 && total < len -4 ; total++) +if (buf[total]) +break ; + +if ((total %4 ) ==0 ) { +/* fast forward over NUL words. */ +for (ibuf = (int *)&buf[total]; + total < len -sizeof (*ibuf) && !*ibuf; + ibuf++) + total +=sizeof (*ibuf); + } + +/* check remainder of a short archive -- it must all be +* zero as both gzip header and cpio header are bigger +* than this. +*/ +if (total >= len -4 ) { +for (;total < len; total++) { +if (buf[len]) { +cpio_error ("Junk at end of buffer" ); + } + } +break ; + }else if (total %4 ) { +/* +* If we are unalinged and not at the end of the buffer +* we must be following a compressed archive. Only +* NUL and gzip headers are allowed. We skipped NUL. +*/ +if (!(buf[total] ==0x1b && buf[total +1 ] ==0x8b )) +cpio_error ("unalinged junk in buffer" ); + } + + this_buf = buf + total; + this_archive =0 ; + +gunzip_start (stream, this_buf, len - total); + +do { + found =check_next_file (path, pathlen, stream, + &this_archive); + }while (!found); + +if (found >0 ) +return found; + +if (stream->s.workspace) { +int discard; + +if (found <-1 ) { +cpio_error ("Junk in compressed archive" ); + } + +/* we either found EOF or TRAILER!!!. In the later +* case we need to discard to the end of the gzip +* contents. +*/ +do { + discard =gunzip_partial (stream, name_buf, +MAX_PATH ); + this_archive += discard; + }while (discard); + +/* +* Peek at how many input bytes were consumed. +* reset our consumed input. +*/ + total += stream->s.total_in +8 ; + +/* clean up zlib */ + discard =gunzip_finish (stream, name_buf,0 ); + }else { +if (this_archive %4 ) { +cpio_error ("Archive not multiple of 4?" ); + } + total += this_archive; + +if (!this_archive) { +cpio_error ("junk between archives" ); + } +/* don't check the < -1 of found, it might be an +* archive. This will be caught by the !this_archive +* check on the next loop. +*/ + } + }while (total < len); + +return 0 ; +} + +void get_cpio_info (void **archive_start,int *consumed) +{ + *archive_start = this_buf; + *consumed = this_archive; +} + +int get_cpio_file_mode (void ) +{ +return cpio_str_to_num (cpio_header_buf.mode); +} + +int get_cpio_file_size (void ) +{ +return cpio_str_to_num (cpio_header_buf.filesize); +}
arch/powerpc/boot/cpio.h new file +12 -0
@@ -0,0 +1,12 @@ +#include "gunzip_util.h" + +extern int find_in_cpio (char *path,struct gunzip_state *stream); +extern int find_in_initramfs (char *path,char *buf,int len, +struct gunzip_state *state); +extern void get_cpio_info (void **archive_start,int *consumed); +extern int get_cpio_file_size (void ); +extern int get_cpio_file_mode (void ); + +#define MAX_PATH 256 + +extern void cpio_error (char *msg);
arch/powerpc/boot/Makefile +2 -2
@@ -36,13 +36,13 @@ $(obj)/ebony.o: BOOTCFLAGS += -mcpu=440 zlib := inffast.c inflate.c inftrees.c zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h -zliblinuxheader := zlib.h zconf.h zutil.h +zliblinuxheader := zlib.h zconf.h zutil.h stat.h $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \ $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ - flatdevtree_conv.c marshal.c memranges.c kexec.c rtas.c \ + flatdevtree_conv.c marshal.c memranges.c kexec.c rtas.c cpio.c \ ns16550.c serial.c simple_alloc.c div64.S util.S \ gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
PATCH 11/15 bootwrapper: allow vmlinuz to be an external payload
In reply to Milton MillerAllow the boot wrapper to obtain the vmlinux elf from an external platform supplied location instead of embedding it at link time.
When used with the cpio library, the kernel can be stored as a file in the initramfs, allowing the same (compressed) copy of the vmlinux elf to be used for both the kernel to execute and any user space tools such as kexec (for reboot), crash dump, or oprofile.
Another use would be to uncompress directly from a memory mapped region such as a flash partition.
---
vs 12178, just fuzz.
The source and source len variables are passed to the routine only to allow them to be printed later.
The gunzip_state is passed to allow a platform to find the elf stream in an arbitrary container (cpio, ar, etc) without decompressing leading data twice.
I also used this hook for qemu, where the "rom" contains the wrapper code and device tree blob, but the kernel is loaded into ram via the -kernel flag (allowing a raw vmlinux elf).
arch/powerpc/boot/main.c +12 -3
@@ -37,10 +37,19 @@ static struct addr_range prep_kernel(voistruct elf_info ei;int len; -/* gunzip the ELF header of the kernel */ -gunzip_start (&gzstate, vmlinuz_addr, vmlinuz_size); -gunzip_exactly (&gzstate, elfheader,sizeof (elfheader)); +/* Initialze zlib. Any attached kernel overrides find_vmlinuz */ +if (vmlinuz_size) +gunzip_start (&gzstate, vmlinuz_addr, vmlinuz_size); +else +if (platform_ops.find_vmlinuz) + platform_ops.find_vmlinuz (&gzstate, &vmlinuz_addr, + &vmlinuz_size); +else +fatal ("Can't find a kernel to boot: no attached " +"vmlinuz and no find_vmlinuz method\n\r" ); +/* gunzip and parse the ELF header of the kernel */ +gunzip_exactly (&gzstate, elfheader,sizeof (elfheader));if (!parse_elf64 (elfheader, &ei) && !parse_elf32 (elfheader, &ei))fatal ("Error: not a valid PPC32 or PPC64 ELF file!\n\r" );
arch/powerpc/boot/ops.h +4 -0
@@ -24,6 +24,8 @@ typedef void (*kernel_entry_t)(unsignedstruct boot_param_header ; +struct gunzip_state ; +/* Platform specific operations */ struct platform_ops {void (*fixups)(void );
@@ -33,6 +35,8 @@ struct platform_ops {void * (*realloc)(void *ptr,unsigned long size);void (*exit)(void );void * (*vmlinux_alloc)(unsigned long size); +void (*find_vmlinuz)(struct gunzip_state *,void **srcp, +unsigned long *lenp); };extern struct platform_ops platform_ops;
PATCH 12/15 bootwrapper: kexec extract vmlinux from initramfs
In reply to Milton MillerTeach the kexec platform to find the vmlinux from the initramfs.
The implementation searches the initramfs for a path specified by the property linux,kernel-path in chosen.
---
vs 12179
change property from boot-file to linux,kernel-path context diffs
arch/powerpc/boot/kexec.c +48 -0
@@ -23,6 +23,8 @@#include "flatdevtree.h" #include "page.h" #include "types.h" +#include "cpio.h" +#include "stat.h" extern char _start[];extern char _end[];
@@ -41,6 +43,51 @@ static void find_console_from_tree(void) } } +void find_vmlinux_in_initramfs (struct gunzip_state *state, +void **srcp,unsigned long *lenp) +{ +void *devp; +int rc; +char path[MAX_PATH ]; + +if (!loader_info.initrd_size) +dt_find_initrd (); +if (!loader_info.initrd_size) +fatal ("find_vmlinux: no initramfs" ); + devp =finddevice ("/chosen" ); +if (!devp) +fatal ("find_vmlinux: no /chosen to find vmlinux" ); + rc =getprop (devp,"linux,kernel-path" , path,sizeof (path)); +if (rc <0 ) + fatal("find_vmlinux: no linux,kernel-path property in /chosen") + else if (rc == 0 || rc > MAX_PATH) +fatal ("linux,kernel-path too long in /chosen" ) + + rc = find_in_initramfs(path, (void *)loader_info.initrd_addr, + loader_info.initrd_size, state); +if (!rc) +fatal ("find_vmlinux: couldn't find linux,kernel-path %s" +" in initramfs" , path); + + rc =get_cpio_file_mode (); +if (!S_ISREG (rc)) +fatal ("find_vmlinux: linux,kernel-path %s is not" + " a regular file", path) + +get_cpio_info (srcp, &rc); + *lenp =get_cpio_file_size (); +} + +void cpio_error (char *msg) +{ +void *srcp; +int read; + +get_cpio_info (&srcp, &read); + +fatal ("cpio_error at %p + 0x%x(%d): %s" , srcp, read, read, msg); +} +/** * setup_initial_heap - setup a small heap in the bss * Using a preallocated heap, setup for scanning the device tree.
@@ -119,6 +166,7 @@ void kexec_platform_init(struct boot_par/* now that we have a malloc region, start over from the flat tree */ init_flat_tree (dt_blob); + platform_ops.find_vmlinuz = find_vmlinux_in_initramfs; platform_ops.vmlinux_alloc = kexec_vmlinux_alloc; platform_ops.fixups = kexec_fixups; finalize_chain = dt_ops.finalize;
PATCH 13/15 bootwrapper: attach an empty vmlinux
In reply to Milton MillerAllow the boot wrapper code to be linked without an attached vmlinux.
Rather than invent a new syntax to invoke the wrapper, attach the stripped version of empty.o, which produces the same result.
This new intermediary is called zBoot.
---
vs 12180
context diffs, identical content
Iniital attempts to remove the dependency on vmlinux in the arch Makefile have lead to multiple make commands competeing in the boot directory and destroying each other. Until the make rules are fixed, the full kenrel must be built.
There are parallel make conflicts when specifying a dts file to be compiled into the binary unaffected by this patch, except one may choose more targets showing the problems..
arch/powerpc/boot/Makefile +7 -2
@@ -126,7 +126,8 @@ endif # args (to if_changed): 1 = (this rule), 2 = platform, 3 = dts 4=dtb 5=initrd quiet_cmd_wrap = WRAP $@ cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \ - $(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux + $(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) \ + $(if $6,$6,vmlinux) kexec-$(CONFIG_PPC32) += zImage.kexec kexec-$(CONFIG_PPC64) += zImage.kexec64
@@ -144,6 +145,7 @@ image-$(CONFIG_PPC_PRPMC2800) += zImage image-$(CONFIG_PPC_ISERIES) += zImage.iseries image-$(CONFIG_DEFAULT_UIMAGE) += uImage image-$(CONFIG_KEXEC) += $(kexec-y) +image-$(CONFIG_KEXEC) += $(patsubst zImage%,zBoot%,$(kexec-y)) ifneq ($(CONFIG_DEVICE_TREE),"") image-$(CONFIG_PPC_8xx) += cuImage.8xx
@@ -197,6 +199,9 @@ $(obj)/vmlinux.strip: vmlinux $(obj)/zImage.iseries: vmlinux $(STRIP) -s -R .comment $< -o $@ +$(obj)/zBoot.%: $(wrapperbits) $(dts) + $(call if_changed,wrap,$*,$(dts),,,$(obj)/empty.o) + $(obj)/zImage.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(STRIP) -s -R .comment $< -o vmlinux.strip $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,)
@@ -234,7 +239,7 @@ clean-files += $(image-) $(initrd-) zIma otheros.bld $(kexec-) # clean up files cached by wrapper -clean-kernel := vmlinux.strip vmlinux.bin +clean-kernel := vmlinux.strip vmlinux.bin empty.o.bin clean-kernel += $(addsuffix .gz,$(clean-kernel)) # If not absolute clean-files are relative to $(obj). clean-files += $(addprefix $(objtree)/, $(clean-kernel))
arch/powerpc/boot/wrapper +7 -0
@@ -161,6 +161,13 @@ ps3) ;; esac +if [ "$kernel" = $object/empty.o ] ; then + ext=bin + objflags="-O binary" + gzip= +fi + + vmz="$tmpdir/`basename \"$kernel\"`.$ext" if [ -z "$cacheit" -o ! -f "$vmz$gzip" -o "$vmz$gzip" -ot "$kernel" ]; then ${CROSS}objcopy $objflags "$kernel" "$vmz.$$"
Re: [PATCH 13/15] bootwrapper: attach an empty vmlinux
Quoted 4 lines · Milton Miller
Allow the boot wrapper code to be linked without an attached vmlinux.
Rather than invent a new syntax to invoke the wrapper, attach the stripped version of empty.o, which produces the same result.
Aiee. Please don't do that. Add a new wrapper option so the vmlinux is optional instead.
Particularly since...
arch/powerpc/boot/wrapper ps3) · line 168
Quoted 13 lines
Index:
kernel/arch/powerpc/boot/wrapper
===================================================================arch/powerpc/boot/wrapper +5
-0@@ -161,6 +161,13 @@ ps3) ;; esac +if [ "$kernel" = $object/empty.o ] ; then + ext=bin + objflags="-O binary" + gzip= +fi
Making the vmlinux empty.o *isn't* just a matter of doing that but also has other side effects as above.
Signature · 4 lines
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/~dgibson
PATCH 14/15 boot: add a hook to start cpus
In reply to Milton MillerThe kexec code is doing strange contortions with dtops.finalize and
platform_ops.vmlinux_alloc to manage the slave cpus. Add a hook
with the needed information.
---
vs 12181
rediff fuzz.
arch/powerpc/boot/kexec.c +2 -24
@@ -117,32 +117,11 @@ static void init_flat_tree(struct boot_pfatal ("Unable to initialize device_tree library!\n\r" ); } -static void *saved_vmlinux_addr; - -static void *kexec_vmlinux_alloc (unsigned long size) -{ -void *addr; - - addr =ranges_vmlinux_alloc (size); - - saved_vmlinux_addr = addr; -return addr; -} -static void kexec_fixups (void ) {wait_slaves_moved (); } -static unsigned long (*finalize_chain)(void ); - -static unsigned long kexec_finalize (void ) -{ -send_slaves_to_kernel (saved_vmlinux_addr); - -return finalize_chain (); -} -void kexec_platform_init (struct boot_param_header *dt_blob) {slaves_are_low ();
@@ -167,8 +146,7 @@ void kexec_platform_init(struct boot_parinit_flat_tree (dt_blob); platform_ops.find_vmlinuz = find_vmlinux_in_initramfs; - platform_ops.vmlinux_alloc = kexec_vmlinux_alloc; + platform_ops.vmlinux_alloc = ranges_vmlinux_alloc; platform_ops.fixups = kexec_fixups; - finalize_chain = dt_ops.finalize; - dt_ops.finalize = kexec_finalize; + platform_ops.start_smp = send_slaves_to_kernel; }
arch/powerpc/boot/main.c +3 -0
@@ -202,6 +202,9 @@ void start(void)else printf (" using OF tree (promptr=%p)\n\r" , loader_info.promptr); +if (platform_ops.start_smp) + platform_ops.start_smp (vmlinux.addr); +if (console_ops.close) console_ops.close ();
arch/powerpc/boot/ops.h +1 -0
@@ -35,6 +35,7 @@ struct platform_ops {void * (*realloc)(void *ptr,unsigned long size);void (*exit)(void );void * (*vmlinux_alloc)(unsigned long size); +void (*start_smp)(void *vmlinux);void (*find_vmlinuz)(struct gunzip_state *,void **srcp,unsigned long *lenp); };
PATCH 15/15 bootwrapper: recheck for command line after fixups
In reply to Milton MillerAfter the fixups hook has run, if we still have not set a command line, check to see if fixups pointed us to one.
Running as a part of fixup allows device tree interaction and error messages to be displayed.
---
The code in main presently checks for the platform providing commandline information before calling the console open or platform fixups "in case the command line data is not safe from overwrite by malloc".
If malloc can overwrite the command line then how do we know flat tree initialization or console search has not already overwritten it? And why would the same argument not apply to the initrd?
If a platform can't adjust malloc to keep the loader supplied command line safe, then it could copy the loader command line to a buffer in bss.
Regardless, this is safe as we will stop once the command line contains any information. My current qemu patch relies on this.
arch/powerpc/boot/main.c +5 -0
@@ -181,6 +181,11 @@ void start(void)if (platform_ops.fixups) platform_ops.fixups (); +/* check again, in case fixups told us about it */ +if ((loader_info.cmdline_len >0 ) && (cmdline[0 ] =='\0' )) +memmove (cmdline, loader_info.cmdline, +min (loader_info.cmdline_len,COMMAND_LINE_SIZE -1 )); +printf ("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r" , _start,get_sp ());
PATCH 1/2 qemu platform, v2
In reply to Milton MillerHere is the second rev of patches to boot a arch powerpc kernel on qemu with the prep architecture.
The goal is to provide an environment for use with the existing qemu hardware suppplied hardware, as oposed to changing the qemu machine description.
This patch contains only the kernel portion. While the diff was generated against for-2.6.24, this first patch applies cleanly to 2.6.23-rc7. With the rom image created in the next patch, a kernel built by this patch should boot when using qemu -kernel.
I debated putting this in the embedded6xx tree, especially when I discovered that the bridge is suposedly a '105, but saw no advantage in the end.
pci config space is now working, however cirrusfb causes crashes and ohci times out, so at least pci memory is likely still broken.
ide and serial work, floppy and parallel are untested.
I added a defconfig based on chrp32; hardware options still need tweaking (eg isa ne2k).
arch/powerpc/platforms/Kconfig +1 -0
@@ -47,6 +47,7 @@ source "arch/powerpc/platforms/chrp/Kcon source "arch/powerpc/platforms/52xx/Kconfig" source "arch/powerpc/platforms/powermac/Kconfig" source "arch/powerpc/platforms/prep/Kconfig" +source "arch/powerpc/platforms/qemu/Kconfig" source "arch/powerpc/platforms/maple/Kconfig" source "arch/powerpc/platforms/pasemi/Kconfig" source "arch/powerpc/platforms/celleb/Kconfig"
arch/powerpc/platforms/qemu/Kconfig new file +10 -0
@@ -0,0 +1,10 @@ +config PPC_QEMU + bool "QEMU emulated PowerPC Reference Platform (PReP) system" + depends on PPC_MULTIPLATFORM && PPC32 + select PPC_I8259 + select PPC_INDIRECT_PCI + select PPC_UDBG_16550 + select PPC_NATIVE + select WANT_DEVICE_TREE + default n +
arch/powerpc/platforms/qemu/Makefile new file +2 -0
@@ -0,0 +1,2 @@ +obj-y += setup.o +obj-$(CONFIG_PCI) += pci.o
arch/powerpc/platforms/qemu/pci.c new file +133 -0
133 lines not on this page · raw message
arch/powerpc/platforms/qemu/setup.c new file +178 -0
178 lines not on this page · raw message
arch/powerpc/platforms/Makefile +1 -0
@@ -17,6 +17,7 @@ obj-$(CONFIG_PPC_82xx) += 82xx/ obj-$(CONFIG_PPC_83xx) += 83xx/ obj-$(CONFIG_PPC_85xx) += 85xx/ obj-$(CONFIG_PPC_86xx) += 86xx/ +obj-$(CONFIG_PPC_QEMU) += qemu/ obj-$(CONFIG_PPC_PSERIES) += pseries/ obj-$(CONFIG_PPC_ISERIES) += iseries/ obj-$(CONFIG_PPC_MAPLE) += maple/
arch/powerpc/configs/qemu_defconfig new file +1217 -0
1,217 lines not on this page · raw message
Re: [PATCH 1/2] qemu platform, v2
Quoted 2 lines · Milton Miller
Here is the second rev of patches to boot a arch powerpc kernel on qemu with the prep architecture.
So if this is supposed to be prep why do you need additional kernel support? And if you really needed why isn't it under platforms/prep?
Re: [PATCH 1/2] qemu platform, v2
Quoted 6 lines · Christoph Hellwig
Quoted 2 lines · Milton Miller
Here is the second rev of patches to boot a arch powerpc kernel on qemu with the prep architecture.
So if this is supposed to be prep why do you need additional kernel support? And if you really needed why isn't it under platforms/prep?
The device tree provided by qemu's open hackware violates some of the assumptions the Linux kernel is making? (Although things like "the cpu cache size is zero" are, technically speaking, probably correct. :)
There are three different problems here:
1) porting prep from arch=ppc to arch=powerpc so you can build it on an arch that also supports make headers_install.
2) PowerPC uses a device tree supplied by the hardware to identify the available hardware, even for stuff living on PCI busses which it could theoretically probe for but doesn't.
3) The PPC firmware qemu comes with ("Open Hackware") sucks rocks, is hard to modify, isn't quite being maintained. As mentioned above, the device tree it passes in (including "prep residual data" from which more nodes in the device tree can be constructed, and here my understanding goes all fuzzy) does not make for a happy Linux kernel.
Proposed solutions to all this involve various combinations of creating a target platform aimed directly at qemu and not pretending to be prep at all (so it doesn't have to parse residual data), creating our own boot rom image out of some of the wrapper code the linux kernel's already got and feeding that to qemu instead of using open hackware at all, hard wiring a device tree into the kernel and not looking at the one open hackware passes in...)
I'd be following this more closely if compiling a device tree didn't currently require an external utility (dtc or some such) that doesn't come with the Linux kernel. No other target platform I've built kernels for requires such an environmental dependency. (This is a problem both for hardwiring the device tree into the kernel and for building a new boot rom from the linux kernel's ppc boot wrapper that would contain such a device tree to feed to the kernel.)
Rob
Signature · 2 lines
"One of my most productive days was throwing away 1000 lines of code." - Ken Thompson.
Re: [PATCH 1/2] qemu platform, v2
Rob Landley writes:
Just to correct a few misconceptions:
Quoted 3 lines
2) PowerPC uses a device tree supplied by the hardware to identify the available hardware, even for stuff living on PCI busses which it could theoretically probe for but doesn't.
The device tree doesn't have to include anything that can be probed for. On some platforms (e.g. pSeries) we choose to use the device tree rather than probing, but on most other platforms we probe.
Quoted 4 lines
I'd be following this more closely if compiling a device tree didn't currently require an external utility (dtc or some such) that doesn't come with the Linux kernel. No other target platform I've built kernels for requires such an environmental dependency.
No? You haven't built kernels for other platforms that have external dependencies such as perl, gcc, make, binutils, etc.? :)
Quoted 4 lines
(This is a problem both for hardwiring the
device tree into the kernel and for building a new boot rom from the linux kernel's ppc boot wrapper that would contain such a device tree to feed to the kernel.)
It's only really been a problem for ps3 so far, since the embedded guys don't seem to have any difficulty with installing dtc. We are looking at what to do for ps3 and prep, and the answer may well involve bundling dtc in the kernel source (it's not too big, around 3400 lines).
Paul.
Re: [PATCH 1/2] qemu platform, v2
Quoted 11 lines · Paul Mackerras
Rob Landley writes:
Just to correct a few misconceptions:
Quoted 3 lines
2) PowerPC uses a device tree supplied by the hardware to identify the available hardware, even for stuff living on PCI busses which it could theoretically probe for but doesn't.
The device tree doesn't have to include anything that can be probed for. On some platforms (e.g. pSeries) we choose to use the device tree rather than probing, but on most other platforms we probe.
Quoted 7 lines
Quoted 4 lines
I'd be following this more closely if compiling a device tree didn't currently require an external utility (dtc or some such) that doesn't come with the Linux kernel. No other target platform I've built kernels for requires such an environmental dependency.
No? You haven't built kernels for other platforms that have external dependencies such as perl, gcc, make, binutils, etc.? :)
Lemme clarify.
1) All of the other platforms have the _same_ requirements. I never had to install anything to build "for arm", "for mips", "for sparc", or for "x86_64".
The minimal requirements are: A compiler (gcc/binutils although I'm working on extending tcc to replace these), make, linux kernel, C library (uClibc), busybox, and bash. That's it. You can rebuild it under itself from source with that, on x86, x86-64, arm, mips... Presumably sparc and m68k too (still debugging there).
2) Perl isn't needed to build any target platform I've tried. (I even sent in some patches way back to turn a perl script into a sed script for User Mode Linux to _make_ this the case.) Yes you need perl to build glibc, but not to build uClibc. :)
3) What I'm pointing out is that ppc needs an external dependency none of the other platforms I've tried need. I consider this a bug. I didn't start using "make headers_install" until it stopped needing an external unifdef.
Quoted 7 lines
Quoted 4 lines
(This is a problem both for hardwiring the
device tree into the kernel and for building a new boot rom from the linux kernel's ppc boot wrapper that would contain such a device tree to feed to the kernel.)It's only really been a problem for ps3 so far, since the embedded guys don't seem to have any difficulty with installing dtc.
If the only target that interested me was ppc, then I'd happily install dtc for it. But focusing on cross-platform support as I am, I notice when a platform has different requirements from any of the others.
Quoted 4 lines
We are
looking at what to do for ps3 and prep, and the answer may well involve bundling dtc in the kernel source (it's not too big, around 3400 lines).
Sounds good to me...
Quoted 1 line
Paul.
Rob
Signature · 2 lines
"One of my most productive days was throwing away 1000 lines of code." - Ken Thompson.
Re: [PATCH 1/2] qemu platform, v2
In reply to Paul MackerrasQuoted 7 lines
Quoted 4 lines
I'd be following this more closely if compiling a device tree didn't currently require an external utility (dtc or some such) that doesn't come with the Linux kernel. No other target platform I've built kernels for requires such an environmental dependency.
No? You haven't built kernels for other platforms that have external dependencies such as perl, gcc, make, binutils, etc.? :)
Two of the supported Linux archs cannot be built with a mainline compiler, even!
And I have to install GNU sed/awk to get builds to work, too.
OTOH, it would be nice if we didn't need DTC -- it itself doesn't build out-of-the-box on all systems, either ;-)
Quoted 10 lines
Quoted 4 lines
(This is a problem both for hardwiring the
device tree into the kernel and for building a new boot rom from the linux kernel's ppc boot wrapper that would contain such a device tree to feed to the kernel.)It's only really been a problem for ps3 so far, since the embedded guys don't seem to have any difficulty with installing dtc. We are looking at what to do for ps3 and prep, and the answer may well involve bundling dtc in the kernel source (it's not too big, around 3400 lines).
If only a few platforms have this problem, we could instead include their .dtb files in the kernel source tree.
Segher
Re: [PATCH 1/2] qemu platform, v2
Quoted 8 lines · Segher Boessenkool
Quoted 8 lines
Quoted 7 lines
I'd be following this more closely if compiling a device tree didn't currently
require an external utility (dtc or some such) that doesn't come with the
Linux kernel. No other target platform I've built kernels for requires such
an environmental dependency.
Quoted 5 lines
Quoted 2 lines
No? You haven't built kernels for other platforms that have external dependencies such as perl, gcc, make, binutils, etc.? :)
Two of the supported Linux archs cannot be built with a mainline compiler, even!
Strange definition of "supported"...
Quoted 1 line
And I have to install GNU sed/awk to get builds to work, too.
I extended busybox sed until it built everything I threw at it. (I even added a "lie to autoconf" step that replies to --version to say "This is not gnu sed 4.0" so a regex in autoconf doesn't do something stupid.)
That's how I got into busybox development in the first place...
Quoted 2 lines
OTOH, it would be nice if we didn't need DTC -- it itself doesn't build out-of-the-box on all systems, either ;-)
I've built x86, x86-64, mips, arm, and sparc. None of them needed anything but the seven packages I mentioned. I'm poking at adding m68k, alpha, bfin, and powerpc, but my free time's been spoken for recently. (I'll become interested in sh or parisc when qemu grows support for it. I'm only interested in bfin because I was given some free blackfin hardware at OLS.)
I've even poked at running s390 under Hercules but the setup was insane enough to throw it way the heck down on my todo list. (Step 1: download and configure an IBM operating system image from the 1970's... Oh yeah, fills me with enthusiasm...)
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
(This is a problem both for hardwiring the
device tree into the kernel and for building a new boot rom from the linux
kernel's ppc boot wrapper that would contain such a device tree to feed to
the kernel.)
Quoted 8 lines
Quoted 5 lines
It's only really been a problem for ps3 so far, since the embedded guys don't seem to have any difficulty with installing dtc. We are looking at what to do for ps3 and prep, and the answer may well involve bundling dtc in the kernel source (it's not too big, around 3400 lines).
If only a few platforms have this problem, we could instead include their .dtb files in the kernel source tree.
I've had it clarified that the recent qemu-ppc patches from Milton only require dtc to build the ROM image to boot qemu with. The Linux kernel image you build hasn't got a device tree in it (although that means it needs one passed in from the rom image)...
Using some other patches that floated by, I did build a prep kernel a couple of weeks ago, which qemu happily handed control off to... which then failed to boot because it couldn't parse the incomplete residual data left over from open hackware. The solution the ppc list recommended? Hardwire a device tree into said linux kernel using dtc...
Quoted 2 lines
Segher
Rob
Signature · 2 lines
"One of my most productive days was throwing away 1000 lines of code." - Ken Thompson.
Re: [PATCH 1/2] qemu platform, v2
In reply to Segher BoessenkoolQuoted 26 lines · Segher Boessenkool
Quoted 10 lines
Quoted 7 lines
I'd be following this more closely if compiling a device tree didn't currently
require an external utility (dtc or some such) that doesn't come with the
Linux kernel. No other target platform I've built kernels for requires such
an environmental dependency.No? You haven't built kernels for other platforms that have external dependencies such as perl, gcc, make, binutils, etc.? :)
Two of the supported Linux archs cannot be built with a mainline compiler, even!
And I have to install GNU sed/awk to get builds to work, too.
OTOH, it would be nice if we didn't need DTC -- it itself doesn't build out-of-the-box on all systems, either ;-)
Quoted 7 lines
Quoted 6 lines
(This is a problem both for hardwiring the
device tree into the kernel and for building a new boot rom from the linux
kernel's ppc boot wrapper that would contain such a device tree to feed to
the kernel.)
Quoted 8 lines
Quoted 5 lines
It's only really been a problem for ps3 so far, since the embedded guys don't seem to have any difficulty with installing dtc. We are looking at what to do for ps3 and prep, and the answer may well involve bundling dtc in the kernel source (it's not too big, around 3400 lines).
If only a few platforms have this problem, we could instead include their .dtb files in the kernel source tree.
Including .dtbs in the kernel tree has a big practical problem:
they're binary, so can't be patch(1)ed, which makes updating them a complete PITA.
I'm working on merging dtc into the kernel tree instead.
Signature · 4 lines
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/~dgibson
Re: [PATCH 1/2] qemu platform, v2
Quoted 33 lines · David Gibson
Quoted 32 lines · Segher Boessenkool
Quoted 10 lines
Quoted 7 lines
I'd be following this more closely if compiling a device tree didn't currently
require an external utility (dtc or some such) that doesn't come with the
Linux kernel. No other target platform I've built kernels for requires such
an environmental dependency.No? You haven't built kernels for other platforms that have external dependencies such as perl, gcc, make, binutils, etc.? :)
Two of the supported Linux archs cannot be built with a mainline compiler, even!
And I have to install GNU sed/awk to get builds to work, too.
OTOH, it would be nice if we didn't need DTC -- it itself doesn't build out-of-the-box on all systems, either ;-)
Quoted 12 lines
Quoted 6 lines
(This is a problem both for hardwiring the
device tree into the kernel and for building a new boot rom from the linux
kernel's ppc boot wrapper that would contain such a device tree to feed to
the kernel.)It's only really been a problem for ps3 so far, since the embedded guys don't seem to have any difficulty with installing dtc. We are looking at what to do for ps3 and prep, and the answer may well involve bundling dtc in the kernel source (it's not too big, around 3400 lines).
Quoted 8 lines
Quoted 2 lines
If only a few platforms have this problem, we could instead include their .dtb files in the kernel source tree.
Including .dtbs in the kernel tree has a big practical problem:
they're binary, so can't be patch(1)ed, which makes updating them a complete PITA.I'm working on merging dtc into the kernel tree instead.
I'm kind of late to this party; but I have to say I disagree. Most of us are doing just fine installing the dtc tool (and mkimage tool for that matter). Cloning it in the kernel tree is just asking for divergence.
Cheers,
g.
Signature · 4 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd. [email protected] (403) 399-0195
Re: [PATCH 1/2] qemu platform, v2
Quoted 3 lines · Grant Likely
Quoted 3 lines
Including .dtbs in the kernel tree has a big practical problem:
they're binary, so can't be patch(1)ed, which makes updating them a complete PITA.
I note that kconfig includes the lex/yacc output files (blah.c_shipped) so you don't have to have lex and yacc installed to run "menuconfig". It _also_ includes the lex/yacc source which is what you patch and rebuild the _shipped files from when they need to be changed.
Quoted 6 lines
Quoted 1 line
I'm working on merging dtc into the kernel tree instead.
I'm kind of late to this party; but I have to say I disagree. Most of us are doing just fine installing the dtc tool (and mkimage tool for that matter). Cloning it in the kernel tree is just asking for divergence.
Milton Miller has some patches that make a "PPC qemu target" kernel image which doesn't include a device tree, and generates a rom image to boot qemu with which contains a device tree and hands it off to the Linux kernel. If qemu can merge that rom image in its BIOS collection, this approach would meet my immediate needs.
Quoted 2 lines
Cheers,
g.
Rob
Signature · 2 lines
"One of my most productive days was throwing away 1000 lines of code." - Ken Thompson.
Re: [PATCH 1/2] qemu platform, v2
In reply to Grant LikelyQuoted 9 lines · Grant Likely
Quoted 3 lines · David Gibson
On Fri, Sep 28, 2007 at 06:53:28PM +0200, Segher Boessenkool wrote:
I'm working on merging dtc into the kernel tree instead.
I'm kind of late to this party; but I have to say I disagree. Most of us are doing just fine installing the dtc tool (and mkimage tool for that matter). Cloning it in the kernel tree is just asking for divergence.
Which begs the question; why cloning?
Why can't development be MOVED to in-kernel?
Signature · 2 lines
Matt Sealey <[email protected]> Genesi, Manager, Developer Relations
Re: [PATCH 1/2] qemu platform, v2
Quoted 5 lines · Matt Sealey
Quoted 4 lines · Grant Likely
Quoted 3 lines · David Gibson
On Fri, Sep 28, 2007 at 06:53:28PM +0200, Segher Boessenkool wrote:
I'm working on merging dtc into the kernel tree instead.
Quoted 8 lines
Quoted 4 lines
I'm kind of late to this party; but I have to say I disagree. Most of us are doing just fine installing the dtc tool (and mkimage tool for that matter). Cloning it in the kernel tree is just asking for divergence.
Which begs the question; why cloning?
Why can't development be MOVED to in-kernel?
Because we don't put userspace testsuites there for one.
And its a stand alone tool and should have its own packaging for a second (ie the kernel provides the kernel and modules, but not random user space utilities, in its tarbal).
If we say only some boards or ports are special and need to build then I would vote for shipping asm files. If we think we need to build any random embedded platform without installing dtc then we should merge dtc.
PS the proposed kbuild integration is wrong; it should build it in the subdirectory.
milton
Re: [PATCH 1/2] qemu platform, v2
Quoted 7 lines · Milton Miller
Quoted 3 lines · Matt Sealey
Which begs the question; why cloning?
Why can't development be MOVED to in-kernel?
Because we don't put userspace testsuites there for one.
Quoted 8 lines
And its a stand alone tool and should have its own packaging for a second (ie the kernel provides the kernel and modules, but not random user space utilities, in its tarbal).
If we say only some boards or ports are special and need to build then I would vote for shipping asm files. If we think we need to build any random embedded platform without installing dtc then we should merge dtc.
I don't think we do. It's looking like there are going to be out of tree users of dtc also (The are some patches floating around for u-boot to use the device tree for it's own initialization). I don't think it's unreasonable to install dtc for embedded development.
I like the idea of shipping asm files to support the qemu target; at least until qemu gets better firmware.
Cheers,
g.
Signature · 4 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd. [email protected] (403) 399-0195
Re: [PATCH 1/2] qemu platform, v2
Quoted 10 lines · Grant Likely
Quoted 4 lines · Milton Miller
If we say only some boards or ports are special and need to build then I would vote for shipping asm files. If we think we need to build any random embedded platform without installing dtc then we should merge dtc.
I don't think we do. It's looking like there are going to be out of tree users of dtc also (The are some patches floating around for u-boot to use the device tree for it's own initialization). I don't think it's unreasonable to install dtc for embedded development.
There are out of tree users of yacc and lex, but the kernel has *.c_shipped files so as not to require that external tool of people who simply want to build the sucker without modifying it. "make oldconfig" was modified not to require curses.
How about *.S_shipped files?
Quoted 2 lines
I like the idea of shipping asm files to support the qemu target; at least until qemu gets better firmware.
I've now gotten qemu to boot a kernel I built, using Milton's 1/2 patch and a a self-contained build of a 4k ppc_boot.rom (which includes the dtc source because I don't expect anybody else to have it installed, either). Description and links to source, binaries, and build scripts in this message:
http://lists.gnu.org/archive/html/qemu-devel/2007-10/msg00415.html
There's a problem with qemu-cvs (detailed in the message), but qemu-system-ppc 0.9.0 boots fine, up to a shell prompt.
Quoted 2 lines
Cheers,
g.
Rob
Signature · 2 lines
"One of my most productive days was throwing away 1000 lines of code." - Ken Thompson.
Re: [PATCH 1/2] qemu platform, v2
In reply to Christoph HellwigQuoted 7 lines · Christoph Hellwig
Quoted 2 lines · Milton Miller
Here is the second rev of patches to boot a arch powerpc kernel on qemu with the prep architecture.
So if this is supposed to be prep why do you need additional kernel support? And if you really needed why isn't it under platforms/prep?
Basically because PReP support doesn't work under arch/powerpc. Getting it working properly is something that should happen, but will take a while. In the meantime, getting something that's sufficient to get working under just qemu's version of prep, without using the abominable openhackware is a quicker path to a usable arch/powerpc kernel under qemu.
Signature · 4 lines
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/~dgibson
Re: [PATCH 1/2] qemu platform, v2
Quoted 6 lines · David Gibson
Basically because PReP support doesn't work under
arch/powerpc. Getting it working properly is something that should happen, but will take a while. In the meantime, getting something that's sufficient to get working under just qemu's version of prep, without using the abominable openhackware is a quicker path to a usablearch/powerpckernel under qemu.
Sounds fair. Care to add something like this to the Kconfig help text?
Re: [PATCH 1/2] qemu platform, v2
Quoted 10 lines · Christoph Hellwig
Quoted 6 lines · David Gibson
Basically because PReP support doesn't work under
arch/powerpc. Getting it working properly is something that should happen, but will take a while. In the meantime, getting something that's sufficient to get working under just qemu's version of prep, without using the abominable openhackware is a quicker path to a usablearch/powerpckernel under qemu.Sounds fair. Care to add something like this to the
Kconfighelp text?
I suppose I could, but actually I wasn't asking for the two qemu patches to be merged. Instead I was posting "here's something that provides minimal function for me, hope you can use it too". For instance, someone should track down pci memory so that ohci and/or video works. Then test the isa ne2ks, or better yet get qemu to change them to pci (except then it only works on the latest qemu).
I didn't put it under prep because it could be changed for the other qemu platforms and doesn't use any thing that makes the machine prep other than some memory map information. I kept prep because I didn't want to deal with io to the scc on b&w G3, the other long-term platform (or with hackware to see if that would just boot as pmac).
milton
PATCH 2/2 qemu platform rom, v2
In reply to Milton MillerHere is the second rev of patches to boot a powerpc port kernel on qemu with the prep architecture.
The goal is to provide a environment for use with the existing qemu hardware suppplied hardware, as oposed to changing the qemu machine description.
This patch has the changes to the boot wrapper and the device tree. It applies to the additon of my kexec series to the for-2.6.24 branch as of 2007/09/21.
The wrapper code zBoot is packaged as ppc_rom.bin, provding a replacement
for OpenHackware. [OpenHackware requires the kernel boot device to
have a partition table, even if its laoded in memory (which prep sort of provides). It also only gueses the execution of boot sripts and any forth, and has noot seen any development in 3 years].
This rom copies its contents to ram where it then invokes the normal wrapper starup path, using the serial port for the console. It proceeds to locate the commandline, kernel, and initrd using nvram. It supports only nvram at the prep location of 0x8000074 indicating a boot from "memory" aka qemu -kernel or drive "m". The loaded image can be a kernel or a zImage (in this mode it will ignore any attached device tree preferring the one supplied via r3), but the contianed kernel and optionally a initrd as per the normal build process will be used.
Specifically, the patch requrires (1) external vmlinux hook and wrapper
(2) check loader_info command line after fixups, and (3) obtain initrd from device-tree, (4) several patches committed to the for-2.6.24 branch.
When building the rom, configure the device tree as "qemu.dts". When building the vmlinux or zImage -kernel, you can use the empty string ("") to suppress the call to dtc as the code will ignore any attached dtb.
When invoking qemu, use the -L flag to specify the directory with the ppc_rom.bin file.
arch/powerpc/boot/qemu.c new file +235 -0
@@ -0,0 +1,235 @@ +/* +* QEMU PReP-specific stuff for the zImage boot wrapper. +* +* Copyright (C) 2007 Milton Miller, IBM Corp. <[email protected]> +* Copyright (C) 2006 Paul Mackerras, IBM Corp. <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of version 2 of the GNU General Public License. +* +* nvram format obtained from OpenHackWare 0.4 +* Copyright (C) 2004-2005 Jocelyn Mayer ([email protected]) +* +*/ + +asm( +/* +* gcc 4.1.2 seems to place this first, even with the block at the end of +* the file. Put it first for good measure. If the branch ends up at the +* beginning of the image then it can be started like a kernel. +*/ +" b _zimage_start\n" /* gcc 4.1.2 places this first */ + +/* +* This code will be loaded by qemu as a rom at the end of memory, and +* execution will start at address -4. Since the rom is read only, we +* and the zImage code wants to run where loaded, we must copy it to ram. +* +* move to linked place +* end with a branch to this code +* this code will be copied with dd to the end of the rom image +*/ + +" .globl copy_rom_start\n" +"copy_rom_start:\n" +" bl 1f\n" +"1: mflr 4\n" +" clrrwi 4,4,19\n" /* ROM_BITS -- get beginning of rom */ +" lis 5,_end@ha\n" +" addi 5,5,_end@l\n" +" lis 3,_start@ha\n" +" addi 3,3,_start@l\n" +" subf 5,3,5\n" +" addi 5,5,0x1f\n" +" srwi 5,5,5\n" +" mtctr 5\n" +"2: lwz 24,0(4)\n" /* copy to linked addresss */ +" lwz 25,4(4)\n" +" lwz 26,8(4)\n" +" lwz 27,12(4)\n" +" lwz 28,16(4)\n" +" lwz 29,20(4)\n" +" lwz 30,24(4)\n" +" lwz 31,28(4)\n" +" stw 24,0(3)\n" +" stw 25,4(3)\n" +" stw 26,8(3)\n" +" stw 27,12(3)\n" +" stw 28,16(3)\n" +" stw 29,20(3)\n" +" stw 30,24(3)\n" +" stw 31,28(3)\n" +" dcbf 0,3\n" +" sync\n" +" icbi 0,3\n" +" addi 3,3,32\n" +" addi 4,4,32\n" +" bdnz 2b\n" +" sync\n" +" isync\n" + +/* +* Put a branch to self on a few vectors in case we get an unexpected +* interrupt. At least you can dump regs in the qemu monitor. +*/ +" lis 0,0x48000000@h\n" +" stw 0,0x700(0)\n" +" stw 0,0x300(0)\n" +" stw 0,0x400(0)\n" +" stw 0,0x900(0)\n" +" stw 0,0x800(0)\n" +" stw 0,0x200(0)\n" + +/* branch to linked address */ +" lis 0,_zimage_start@h\n" +" ori 0,0,_zimage_start@l\n" +" mtctr 0\n" +" li 3,0\n" +" bctrl\n" + +/* must be last word before copy_rom_end */ +" b copy_rom_start\n" +" .globl copy_rom_end\n" +"copy_rom_end:\n" +); + + +#include <stddef.h> +#include "string.h" +#include "stdio.h" +#include "ops.h" +#include "page.h" +#include "io.h" +#include "gunzip_util.h" +#include "flatdevtree.h" + +BSS_STACK (16 *1024 ); + +unsigned char *nvram = (void *)0x80000074 ;/* address of nvram on PReP */ + +static void qemu_nvram_write (unsigned short addr,char data) +{ +out_8 (nvram +0 , addr &0xff ); +out_8 (nvram +1 , addr >>8 ); +out_8 (nvram +3 , data); +} + +static char qemu_nvram_read (unsigned short addr) +{ +char data; +out_8 (nvram +0 , addr &0xff ); +out_8 (nvram +1 , addr >>8 ); + data =in_8 (nvram +3 ); + +return data; +} + +static void qemu_nvram_fetch (unsigned short addr,unsigned short len,void *p) +{ +char *buf = p; +int i; + +for (i =0 ; i < len; i ++) + buf[i] =qemu_nvram_read (addr + i);/* big endian */ +} + +static char arch[17 ]; +static void * image_start; +static unsigned int image_len; + +void qemu_find_vmlinuz (struct gunzip_state *state,void **srcp, +unsigned long *lenp) +{ + *srcp = image_start; + *lenp = image_len; +gunzip_start (state, image_start, image_len); +} + +/* if no device tree, read the nvram to find out about our system */ +/* based on openhackware 0.4 nvram.c get_nvram_config */ +static void qemu_fixups (void ) +{ +char buf[32 ]; +int word; + +printf ("qemu_fixups\n\r" ); + +qemu_nvram_fetch (0 ,16 , buf); +printf ("sig: %s" , buf); +if (strcmp (buf,"QEMU_BIOS" )) +fatal ("no qemu sig found" ); +qemu_nvram_fetch (0x10 ,16 , &word); +if (word !=2 ) +fatal ("wrong qemu nvram version" ); +/* compute crc over 0-0xfc, compare to crc in 0xfc */ +/* size at 0x14, mult 256 0x400-0x2000 */ +qemu_nvram_fetch (0x20 ,16 , buf); +strncpy (arch, buf,sizeof (arch)-1 ); +if (strcmp (arch,"PREP" )) +fatal ("don't understand arch %s" , arch); + +/* XXX: put the model in the device tree */ + +qemu_nvram_fetch (0x30 ,16 , &word); +printf ("memory: %x\n\r" , word); +dt_fixup_memory (0 , word); +printf ("boot device %c\n\r" ,qemu_nvram_read (0x34 )); +qemu_nvram_fetch (0x38 ,16 , &word); + image_start = (void *)word; +qemu_nvram_fetch (0x3c ,16 , &word); + image_len = word; +printf ("kernel %p %x\n\r" , image_start, image_len); +qemu_nvram_fetch (0x40 ,16 , &word); + loader_info.cmdline = (void *)word; +qemu_nvram_fetch (0x44 ,16 , &word); + loader_info.cmdline_len = word; +printf ("cmdline %p %x\n\r" , loader_info.cmdline, + loader_info.cmdline_len); +printf ("cmdline is %s\n\r" , loader_info.cmdline); +qemu_nvram_fetch (0x48 ,16 , &word); + loader_info.initrd_addr = word; +qemu_nvram_fetch (0x4c ,16 , &word); + loader_info.initrd_size = word; +printf ("initrd %lx %lx\n\r" , loader_info.initrd_addr, + loader_info.initrd_size); +/* XXX: nvram image addr at 50 */ +/* XXX: vga width, height, depth = shorts at 54, 56, 58 */ +} + +/* If loaded with a device tree, then just read the tree */ +static void tree_fixups (void ) +{ +/* get initrd from tree */ +dt_find_initrd (); + +/* we must have an attached image for boot with supplied device-tree */ +} + +static void *heap_end;/* set in platform_init */ + +static void *qemu_vmlinux_alloc (unsigned long size) +{ +if (size < (unsigned long )_start) +return 0 ; + +return (void *)_ALIGN_UP ((unsigned long ) heap_end,4096 ); +} + +void platform_init (void *r3) +{ +struct boot_param_header *bph = r3; + + heap_end =simple_alloc_init (_end,4096 *1024 ,4096 ,512 ); + +if (bph) { +ft_init (bph, bph->totalsize,128 ); + platform_ops.fixups = tree_fixups; + }else { +ft_init (_dtb_start, _dtb_end - _dtb_start,128 ); + platform_ops.fixups = qemu_fixups; + platform_ops.find_vmlinuz = qemu_find_vmlinuz; + } + platform_ops.vmlinux_alloc = qemu_vmlinux_alloc; + +serial_console_init (); +}
arch/powerpc/boot/dts/qemu.dts new file +132 -0
132 lines not on this page · raw message
arch/powerpc/boot/wrapper +49 -0
53 lines not on this page · raw message
arch/powerpc/boot/.gitignore +1 -0
@@ -17,6 +17,7 @@ infutil.h kernel-vmlinux.strip.c kernel-vmlinux.strip.gz mktree +ppc_rom.bin uImage cuImage.* zImage
arch/powerpc/boot/Makefile +7 -3
@@ -48,7 +48,7 @@ src-wlib := string.S crt0.S stdio.c main 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \ cpm-serial.c stdlib.c src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c crt0_kexec.S \ - cuboot-ebony.c treeboot-ebony.c prpmc2800.c \ + cuboot-ebony.c treeboot-ebony.c prpmc2800.c qemu.c \ ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \ cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c cuboot-bamboo.c src-boot := $(src-wlib) $(src-plat) empty.c
@@ -143,6 +143,7 @@ image-$(CONFIG_PPC_PMAC) += zImage.pmac image-$(CONFIG_PPC_HOLLY) += zImage.holly image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800 image-$(CONFIG_PPC_ISERIES) += zImage.iseries +image-$(CONFIG_PPC_QEMU) += zImage.qemu zBoot.qemu image-$(CONFIG_DEFAULT_UIMAGE) += uImage image-$(CONFIG_KEXEC) += $(kexec-y) image-$(CONFIG_KEXEC) += $(patsubst zImage%,zBoot%,$(kexec-y))
@@ -202,6 +203,9 @@ $(obj)/zImage.iseries: vmlinux $(obj)/zBoot.%: $(wrapperbits) $(dts) $(call if_changed,wrap,$*,$(dts),,,$(obj)/empty.o) +# horrible hack to avoid overlapping calls to wrapper script clobbering dtb. +$(obj)/zImage.qemu: $(obj)/zBoot.qemu + $(obj)/zImage.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(STRIP) -s -R .comment $< -o vmlinux.strip $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,)
@@ -235,8 +239,8 @@ install: $(CONFIGURE) $(addprefix $(obj) sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $< # anything not in $(targets) -clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \ - otheros.bld $(kexec-) +clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* +clean-files += otheros.bld ppc_rom.bin $(kexec-) # clean up files cached by wrapper clean-kernel := vmlinux.strip vmlinux.bin empty.o.bin