Appended DTB files for multi-machine kernels
Hi,
I'm facing a problem with a transition from legacy board-file driven ARM machines to DTB, and I'm under the impression that a solution for it could be of broader interest.
In short, devices that have been deployed in quantities come in three hardware variants, which all boot with a unique machine-id. We ship kernel images that have board support for all three machine types, and do minor fixups to platform data of some drivers at runtime, depending on the board revision number (passed in via ATAGs).
The built-in support for attaching a DTB to the zImage does not suffice here, because we have one image for all models, and also, we couldn't do a 'per-board-revision' selection that way either.
Unless I missed some recent discussion, this case is not easy to handle. Yes, I know that these kind of things should be handled by a next-generation bootloader, but in our case, we want to avoid a loader update of already shipped hardware by all means.
As a solution, I'm thinking of a small framework that could for example work as follows.
a) A small mechanism allows storing multiple DTB binary files inside the kernel binary at compile time, and a simple function can extract them again by name at runtime (something like what the firmware framework does, but I don't know if that one can be used at such an early stage in the boot process).
b) A DT_MACHINE_START-like macro takes both the machine ID and the name of a DTB file that is compiled in. When matched, generic functions would load the given file, populate the device tree and then conduct a generic DT boot for the specified platform.
c) Allow users to open-code the DTB lookup depending on whatever kind of runtime information (be it the board_revision or anything else).
Of course, everything has to be an opt-in that stubs itself out at zero costs if not needed.
I'm open to opinion and sugesstions :)
Thanks,
Daniel
Quoted 4 lines · Daniel Mack
Unless I missed some recent discussion, this case is not easy to handle. Yes, I know that these kind of things should be handled by a next-generation bootloader, but in our case, we want to avoid a loader update of already shipped hardware by all means.
There was some discussion about appending multiple DTBs recently. I can't actually recall anything about it though so that's not an entirely helpful thing...
Quoted 8 lines
As a solution, I'm thinking of a small framework that could for example work as follows.
a) A small mechanism allows storing multiple DTB binary files inside the kernel binary at compile time, and a simple function can extract them again by name at runtime (something like what the firmware framework does, but I don't know if that one can be used at such an early stage in the boot process).
Another way of skinning this would be for either the kernel to contain
a set of machine ID to compatible string mappings or for the device
trees for the boards to have an additional properties giving the machine
IDs that the boards match. The kernel could then look for multiple DTBs
appended to the image and try to pick one based on ATAGs.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130704/ecc19fcd/attachment.sig>
Quoted 10 lines · Mark Brown
Quoted 4 lines · Daniel Mack
Unless I missed some recent discussion, this case is not easy to handle. Yes, I know that these kind of things should be handled by a next-generation bootloader, but in our case, we want to avoid a loader update of already shipped hardware by all means.
There was some discussion about appending multiple DTBs recently. I can't actually recall anything about it though so that's not an entirely helpful thing...
Yes, it keeps coming up, I think by now everybody agreed it's a good idea to extend the ATAGS compat mode, but so far nobody has implemented it. Magnus Damm was very interested in this feature last year and was planning to work on it, but I don't know how far he got.
Quoted 9 lines
Quoted 8 lines
As a solution, I'm thinking of a small framework that could for example work as follows.
a) A small mechanism allows storing multiple DTB binary files inside the kernel binary at compile time, and a simple function can extract them again by name at runtime (something like what the firmware framework does, but I don't know if that one can be used at such an early stage in the boot process).
Quoted 5 lines
Another way of skinning this would be for either the kernel to contain a set of machine ID to compatible string mappings or for the device trees for the boards to have an additional properties giving the machine IDs that the boards match. The kernel could then look for multiple DTBs appended to the image and try to pick one based on ATAGs.
IIRC there is actually an unused field in the dtb header that could be used to match a board ID.
Arnd
Hi Arnd,
Quoted 10 lines · Arnd Bergmann
Quoted 5 lines · Mark Brown
Another way of skinning this would be for either the kernel to contain a set of machine ID to compatible string mappings or for the device trees for the boards to have an additional properties giving the machine IDs that the boards match. The kernel could then look for multiple DTBs appended to the image and try to pick one based on ATAGs.
IIRC there is actually an unused field in the dtb header that could be used to match a board ID.
While that would help many users, it doesn't cover our case where different board revisions require different DTBs to be loaded, depending on the supplied ATAG.
I think I'll go for Nicolas Pitre's suggestion as first step. He's right that's it's a hack anyway, and we're just dealing with legacy systems here, and hence it might not even be worth caring too much about a proper solution.
Thanks for all the answers,
Daniel
Hi Arnd,
Quoted 8 lines · Arnd Bergmann
Quoted 7 lines · Mark Brown
Quoted 4 lines · Daniel Mack
Unless I missed some recent discussion, this case is not easy to handle. Yes, I know that these kind of things should be handled by a next-generation bootloader, but in our case, we want to avoid a loader update of already shipped hardware by all means.
Quoted 8 lines
Quoted 3 lines
There was some discussion about appending multiple DTBs recently. I can't actually recall anything about it though so that's not an entirely helpful thing...
Yes, it keeps coming up, I think by now everybody agreed it's a good idea to extend the ATAGS compat mode, but so far nobody has implemented it. Magnus Damm was very interested in this feature last year and was planning to work on it, but I don't know how far he got.
Correct, I was and still am a bit interested in it. I did however never get around to write any code. My apologies if that stalled anyone.
With mach-shmobile we're now getting to a point where most of our boards are using DT_MACHINE and appended DTB instead of the MACHINE and mach-type. Because of that I feel that the moment has sort of passed for me.
Regardless of this nearly all our boot loaders pass mach-type so it would be nice to match on that instead of the appended DTB.
Thanks,
/ magnus
Quoted 39 lines · Daniel Mack
Hi,
I'm facing a problem with a transition from legacy board-file driven ARM machines to DTB, and I'm under the impression that a solution for it could be of broader interest.
In short, devices that have been deployed in quantities come in three hardware variants, which all boot with a unique machine-id. We ship kernel images that have board support for all three machine types, and do minor fixups to platform data of some drivers at runtime, depending on the board revision number (passed in via ATAGs).
The built-in support for attaching a DTB to the zImage does not suffice here, because we have one image for all models, and also, we couldn't do a 'per-board-revision' selection that way either.
Unless I missed some recent discussion, this case is not easy to handle. Yes, I know that these kind of things should be handled by a next-generation bootloader, but in our case, we want to avoid a loader update of already shipped hardware by all means.
As a solution, I'm thinking of a small framework that could for example work as follows.
a) A small mechanism allows storing multiple DTB binary files inside the kernel binary at compile time, and a simple function can extract them again by name at runtime (something like what the firmware framework does, but I don't know if that one can be used at such an early stage in the boot process).
b) A DT_MACHINE_START-like macro takes both the machine ID and the name of a DTB file that is compiled in. When matched, generic functions would load the given file, populate the device tree and then conduct a generic DT boot for the specified platform.
c) Allow users to open-code the DTB lookup depending on whatever kind of runtime information (be it the
board_revisionor anything else).
Quoted 5 lines
Of course, everything has to be an opt-in that stubs itself out at zero costs if not needed.
I'm open to opinion and sugesstions :)
What you describe above more or less fits the definition of what I called the "impedance matcher". However it doesn't need to be part of the kernel at all. But you should make it into a separate binary.
Please have a look at the bottom of this post for a more comprehensive
description: http://article.gmane.org/gmane.linux.ports.arm.kernel/242929
Nicolas
Hi Nicolas,
Quoted 9 lines · Nicolas Pitre
Quoted 1 line · Daniel Mack
I'm open to opinion and sugesstions :)
What you describe above more or less fits the definition of what I called the "impedance matcher". However it doesn't need to be part of the kernel at all. But you should make it into a separate binary.
Please have a look at the bottom of this post for a more comprehensive
description: http://article.gmane.org/gmane.linux.ports.arm.kernel/242929
Thanks for the link. Interesting read indeed.
The only thing I'm pondering about is that we already have generic loader code in Linux and a build system that supports a wide range of platforms. I don't know whether it's worth opening that can of worms again and re-implement all details about load addresses, compiler flags, device-tree parsing code yet once again. At least in terms of LOCs, we would certainly be better off doing it inside the kernel.
But I generally second your opinion about pushing vendors to do it right, so I might give that approach a shot soon; there is no code yet anywhere I take it?
Thanks,
Daniel
Quoted 13 lines · Daniel Mack
Hi Nicolas,
Quoted 9 lines · Nicolas Pitre
Quoted 1 line · Daniel Mack
I'm open to opinion and sugesstions :)
What you describe above more or less fits the definition of what I called the "impedance matcher". However it doesn't need to be part of the kernel at all. But you should make it into a separate binary.
Please have a look at the bottom of this post for a more comprehensive
description: http://article.gmane.org/gmane.linux.ports.arm.kernel/242929
Quoted 8 lines
Thanks for the link. Interesting read indeed.
The only thing I'm pondering about is that we already have generic loader code in Linux and a build system that supports a wide range of platforms. I don't know whether it's worth opening that can of worms again and re-implement all details about load addresses, compiler flags, device-tree parsing code yet once again. At least in terms of LOCs, we would certainly be better off doing it inside the kernel.
That is still code with relatively low value that has to be carried and maintained.
And if you do it for your own device outside of the kernel then you can literally hack it the way you want quickly and forget about it once it works. Since this is useful for legacy setups only, you do not have to care about maintaining it in the future.
Quoted 3 lines
But I generally second your opinion about pushing vendors to do it right, so I might give that approach a shot soon; there is no code yet anywhere I take it?
Not that I'm aware of, besides parts of libfdt and atags_to_fdt.c from the kernel tree that can be lifted and modified according to your needs. I don't imagine you'd need much more than that anyway.
Nicolas
Quoted 8 lines · Nicolas Pitre
Quoted 6 lines · Daniel Mack
In short, devices that have been deployed in quantities come in three hardware variants, which all boot with a unique machine-id. We ship kernel images that have board support for all three machine types, and do minor fixups to platform data of some drivers at runtime, depending on the board revision number (passed in via ATAGs).
Quoted 6 lines
What you describe above more or less fits the definition of what I called the "impedance matcher". However it doesn't need to be part of the kernel at all. But you should make it into a separate binary.
Please have a look at the bottom of this post for a more comprehensive
description: http://article.gmane.org/gmane.linux.ports.arm.kernel/242929
FWIW, I gave that approach a try today for a PXA based hardware platform, and in fact it seems to work very well. Thanks again for sharing the idea.
In case anyone is interested, the repository is here:
https://github.com/zonque/pxa-impedance-matcher
As the README says, it's completely specific to my use case, but maybe anyone can use the code base to spin a different version for a different board.
Daniel
Quoted 20 lines · Daniel Mack
Quoted 8 lines · Nicolas Pitre
Quoted 6 lines · Daniel Mack
In short, devices that have been deployed in quantities come in three hardware variants, which all boot with a unique machine-id. We ship kernel images that have board support for all three machine types, and do minor fixups to platform data of some drivers at runtime, depending on the board revision number (passed in via ATAGs).
Quoted 6 lines
What you describe above more or less fits the definition of what I called the "impedance matcher". However it doesn't need to be part of the kernel at all. But you should make it into a separate binary.
Please have a look at the bottom of this post for a more comprehensive
description: http://article.gmane.org/gmane.linux.ports.arm.kernel/242929FWIW, I gave that approach a try today for a PXA based hardware platform, and in fact it seems to work very well. Thanks again for sharing the idea.
Quoted 7 lines
In case anyone is interested, the repository is here:
https://github.com/zonque/pxa-impedance-matcher
As the README says, it's completely specific to my use case, but maybe anyone can use the code base to spin a different version for a different board.
That looks nice, but I'd suggest going a step further if possible.
If you could load the kernel zImage independently with a separate load command in u-boot, then people could update their kernel only without having to relink with this shim. The load address for that zImage can be totally arbitrary as longas it is known to be the same from within this shim and in the u-boot script.
Also, more related to your code, you apparently link and load it to run at 0xa0008000. This is also where the zImage code is going to decompress the final kernel image after it has relocated itself. I'm afraid the DTBs you point to might be overwritten at that point since zImage is not aware of them (in fact I'm surprized this works at all as you say). If I were you I'd use 0xa1000000 instead (and make sure the initrd is out of the way as well if you have one).
Nicolas
cover impedance-matcher generic improvements
In reply to Daniel MackDaniel,
Here's a patch (plus a cscope target) to attempt to make the impedance-matcher generic code. Hopefully I'll have time to test tomorrow. All I can say atm is that it compiles cleanly with and without specifying an appended zImage.
Warning: the code in string.c is little better than psuedo-code, maybe not even that good. I'm posting this so if anyone else is inclined to work on this, there's no need to duplicate effort. And, I have a firm belief in the motivating effects af posting half-assed code. ;-)
Basic idea is to replace a device's stock kernel with this impedance-matcher. Load the kernel and/or the devicetree blob to desired addresses. Add 'loadaddrs=0xXXXXXXXX,0xYYYYYYYY' to the kernel's command line. Or, if you are appending, 'loadaddrs=appended,0xYYYYYYYY'. First address is the location of the kernel, second is the location of the dtb.
Then, for u-boot, 'bootm 0xZZZZZZZZ' where 0xZZZZZZZZ is the address of the impedance-matcher.
For those interested, a public branch can be found at (prone to rebase!):
git://git.infradead.org/users/jcooper/impedance-matcher.git master
Thomas,
You weren't in the original Cc: of this thread, I added you because this may help with your shifting register base address issues.
thx,
Jason.
Jason Cooper (2):
add cscope Makefile target
WIP: Get kernel and dtb addresses from command line
.gitignore | 1 + Makefile | 31 ++++++++++------------ atags.h | 6 +++++ board.c | 88 -------------------------------------------------------------- board.h | 13 ---------- led.c | 54 -------------------------------------- led.h | 6 ----- main.c | 52 +++++++++++++++++++++---------------- string.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ string.h | 8 ++++++ 10 files changed, 141 insertions(+), 201 deletions(-) delete mode 100644 board.c delete mode 100644 board.h delete mode 100644 led.c delete mode 100644 led.h create mode 100644 string.c create mode 100644 string.h
Signature · 1 line
1.8.3.2
PATCH 1/2 add cscope Makefile target
--- .gitignore | 1 + Makefile | 6 ++++++ 2 files changed, 7 insertions(+)
.gitignore +1 -0
@@ -1,6 +1,7 @@ *.sh *.o *.bin +cscope.* matcher uImage input/zImage
Makefile +6 -0
@@ -43,3 +43,9 @@ uImage: matcher.bin clean: rm -fr matcher.bin matcher *.o uImage +distclean: + rm -fr cscope.* + +cscope: + -find . -name "*.[chS]" >cscope.files + -cscope -b -R
Signature · 1 line
1.8.3.2
RFC PATCH 2/2 WIP: Get kernel and dtb addresses from command line
In reply to Jason CooperAllow for detached kernel and dtb images.
--- Makefile | 25 ++++++------------ atags.h | 6 +++++ board.c | 88 ---------------------------------------------------------------- board.h | 13 ---------- led.c | 54 --------------------------------------- led.h | 6 ----- main.c | 52 +++++++++++++++++++++----------------- string.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ string.h | 8 ++++++ 9 files changed, 134 insertions(+), 201 deletions(-) delete mode 100644 board.c delete mode 100644 board.h delete mode 100644 led.c delete mode 100644 led.h create mode 100644 string.c create mode 100644 string.h
Makefile +8 -17
@@ -1,4 +1,10 @@ -CFLAGS=-Wall -ffreestanding +ifeq ($(origin APPEND_IMAGE), undefined) +DOAPPEND= +else +DOAPPEND=-DAPPENDED_IMAGE=1 +endif + +CFLAGS=-Wall -ffreestanding $(DOAPPEND) LDFLAGS=-static -nostdlib GCC=$(CROSS_COMPILE)gcc OBJCOPY=$(CROSS_COMPILE)objcopy
@@ -6,30 +12,15 @@ LD=$(CROSS_COMPILE)ld LOADADDR=0xa0008000 BINFMT=elf32-littlearm -INPUT_OBJS = \ - zimage.o \ - dtb-raumfeld-controller-0.o \ - dtb-raumfeld-controller-1.o \ - dtb-raumfeld-controller-2.o \ - dtb-raumfeld-connector-0.o \ - dtb-raumfeld-connector-1.o \ - dtb-raumfeld-connector-2.o \ - dtb-raumfeld-speaker-0.o \ - dtb-raumfeld-speaker-1.o \ - dtb-raumfeld-speaker-2.o - all: uImage -dtb-%.o: input/%.dtb - $(OBJCOPY) -I binary -O $(BINFMT) -B arm $^ $@ - zimage.o: input/zImage $(OBJCOPY) -I binary -O $(BINFMT) -B arm $^ $@ %.o: %.c $(GCC) $(CFLAGS) -c $^ -matcher: main.o print.o board.o led.o $(INPUT_OBJS) +matcher: main.o print.o string.o $(APPEND_IMAGE) $(LD) $(LDFLAGS) -T matcher.lds -o $@ $^ matcher.bin: matcher
atags.h +6 -0
@@ -10,15 +10,21 @@ struct tag_header {/* board revision */ #define ATAG_REVISION 0x54410007 +#define ATAG_CMDLINE 0x54410009struct tag_revision {__u32 rev; }; +struct tag_cmdline { +char cmdline[1 ];/* this is the minimum size */ +}; +struct tag {struct tag_header hdr;union {struct tag_revision rev; +struct tag_cmdline cmdline; } u; };
board.c deleted +0 -88
88 lines not on this page · raw message
board.h deleted +0 -13
@@ -1,13 +0,0 @@ -#ifndef _BOARD_H -#define _BOARD_H - -struct board { -__u32 machid; -__u32 system_rev; -void *dtb; -const char *name; -}; - -struct board *match_board (__u32 machid,__u32 revision); - -#endif
led.c deleted +0 -54
54 lines not on this page · raw message
led.h deleted +0 -6
@@ -1,6 +0,0 @@ -#ifndef _LED_H_ -#define _LED_H_ - -void led_panic (void ); - -#endif
main.c +29 -23
74 lines not on this page · raw message
string.c new file +83 -0
83 lines not on this page · raw message
string.h new file +8 -0
@@ -0,0 +1,8 @@ +#ifndef _STRING_H_ + +#include "types.h" + +int strncmp (const char *,const char *,int ); +void *gethexaddr (const char *,const char **); +int getaddrs (void **,void **,const char *); +#endif
Signature · 1 line
1.8.3.2
cover impedance-matcher generic improvements
In reply to Jason CooperHi Jason,
Quoted 5 lines · Jason Cooper
Basic idea is to replace a device's stock kernel with this impedance-matcher. Load the kernel and/or the devicetree blob to desired addresses. Add 'loadaddrs=0xXXXXXXXX,0xYYYYYYYY' to the kernel's command line. Or, if you are appending, 'loadaddrs=appended,0xYYYYYYYY'. First address is the location of the kernel, second is the location of the dtb.
Nice to see that idea implemented! For me though, changing any of the U-Boot variables is out of the question, and I need the matcher just the way I implemented it, including the LED blink pattern to let the user know if things go wrong.
Hence, I won't change to your generic version on my boards, and so I think it might be best if you maintain your own tree for your approach.
Best regards,
Daniel
cover impedance-matcher generic improvements
Quoted 9 lines · Daniel Mack
Hi Jason,
Quoted 5 lines · Jason Cooper
Basic idea is to replace a device's stock kernel with this impedance-matcher. Load the kernel and/or the devicetree blob to desired addresses. Add 'loadaddrs=0xXXXXXXXX,0xYYYYYYYY' to the kernel's command line. Or, if you are appending, 'loadaddrs=appended,0xYYYYYYYY'. First address is the location of the kernel, second is the location of the dtb.
Quoted 4 lines
Nice to see that idea implemented! For me though, changing any of the U-Boot variables is out of the question, and I need the matcher just the way I implemented it, including the LED blink pattern to let the user know if things go wrong.
Understandable. After thinking about it a bit, I think I'm going to rework this patch to allow appending both kernels and dtbs (as you had), and abstract out the led blink so that your code would become a compile time option.
Quoted 2 lines
Hence, I won't change to your generic version on my boards, and so I think it might be best if you maintain your own tree for your approach.
hrmmm, I don't like forking on general principle. Let me do the above rework and see if that works for you, while adding the capabilities I need.
When I'm done, you should just be able to do:
$ make APPEND_KERNEL=input/zImage APPEND_DTBS=input/*.dtb uImage
And get the same result.
In the meantime, would you mind adding a license to your code? If you have no preference, I like GPLv2-only, but it's your code, so whatever you like.
thx,
Jason.
cover impedance-matcher generic improvements
Hi Jason,
Quoted 13 lines · Jason Cooper
Quoted 11 lines · Daniel Mack
Quoted 5 lines · Jason Cooper
Basic idea is to replace a device's stock kernel with this impedance-matcher. Load the kernel and/or the devicetree blob to desired addresses. Add 'loadaddrs=0xXXXXXXXX,0xYYYYYYYY' to the kernel's command line. Or, if you are appending, 'loadaddrs=appended,0xYYYYYYYY'. First address is the location of the kernel, second is the location of the dtb.
Nice to see that idea implemented! For me though, changing any of the U-Boot variables is out of the question, and I need the matcher just the way I implemented it, including the LED blink pattern to let the user know if things go wrong.
Quoted 4 lines
Understandable. After thinking about it a bit, I think I'm going to rework this patch to allow appending both kernels and dtbs (as you had), and abstract out the led blink so that your code would become a compile time option.
And how would you match machids and system_rev values to the dtb files? This is how I identify my boards at least. But as Stephen Warren said in the thread that started this discussion, there might be totally different ways of detection. For instance, other boards could read GPIO lines, or even have a pseudo driver that initializes the I2C controller in order to talk to an EEPROM or such. Reading from an ADC is another option.
And the more I think about it, I believe Nicolas was right in saying that such a thing does not need to be very generic (as much as I like generic solutions in principle).
If at all, I think we should start thinking of that code base as something like a framework, consisting of a merely empty main() function body, a lds linker script and some objcopy magic in the Makefile. And then have a menuconfig which allows to select one out of many hardware types, which then uses its specific way of board detection, LED signaling and so on. The two lines of vectoring to the actual kernel can be generic then. But again, I really don't know if it's worth the hassle.
Quoted 7 lines
hrmmm, I don't like forking on general principle. Let me do the above rework and see if that works for you, while adding the capabilities I need.
When I'm done, you should just be able to do:
$ make APPEND_KERNEL=input/zImage APPEND_DTBS=input/*.dtb uImage
Out of curiosity, I'd like to see how you dynamically create the symbol definitions for the binary blobs :)
Quoted 3 lines
In the meantime, would you mind adding a license to your code? If you have no preference, I like GPLv2-only, but it's your code, so whatever you like.
Done, GPLv2 it is.
Thanks,
Daniel
cover impedance-matcher generic improvements
Quoted 16 lines · Daniel Mack
Hi Jason,
Quoted 13 lines · Jason Cooper
Quoted 11 lines · Daniel Mack
Quoted 5 lines · Jason Cooper
Basic idea is to replace a device's stock kernel with this impedance-matcher. Load the kernel and/or the devicetree blob to desired addresses. Add 'loadaddrs=0xXXXXXXXX,0xYYYYYYYY' to the kernel's command line. Or, if you are appending, 'loadaddrs=appended,0xYYYYYYYY'. First address is the location of the kernel, second is the location of the dtb.
Nice to see that idea implemented! For me though, changing any of the U-Boot variables is out of the question, and I need the matcher just the way I implemented it, including the LED blink pattern to let the user know if things go wrong.
Quoted 6 lines
Quoted 4 lines
Understandable. After thinking about it a bit, I think I'm going to rework this patch to allow appending both kernels and dtbs (as you had), and abstract out the led blink so that your code would become a compile time option.
And how would you match machids and
system_revvalues to the dtb files?
I'm thinking board-specific match functions. For your use case, you would match machid/system_rev to a compatible string. Then, generic code would scan the appended dtbs for a matching string.
Quoted 6 lines
This is how I identify my boards at least. But as Stephen Warren said in the thread that started this discussion, there might be totally different ways of detection. For instance, other boards could read GPIO lines, or even have a pseudo driver that initializes the I2C controller in order to talk to an EEPROM or such. Reading from an ADC is another option.
As long as it resolves to a compatible string.
Quoted 16 lines
And the more I think about it, I believe Nicolas was right in saying that such a thing does not need to be very generic (as much as I like generic solutions in principle).
If at all, I think we should start thinking of that code base as something like a framework, consisting of a merely empty
main()function body, a lds linker script and some objcopy magic in theMakefile. And then have a menuconfig which allows to select one out of many hardware types, which then uses its specific way of board detection, LED signaling and so on. The two lines of vectoring to the actual kernel can be generic then. But again, I really don't know if it's worth the hassle.Quoted 4 lines
hrmmm, I don't like forking on general principle. Let me do the above rework and see if that works for you, while adding the capabilities I need.
Quoted 6 lines
Quoted 3 lines
When I'm done, you should just be able to do:
$ make APPEND_KERNEL=input/zImage APPEND_DTBS=input/*.dtb uImageOut of curiosity, I'd like to see how you dynamically create the symbol definitions for the binary blobs :)
Me too. ;-)
Quoted 5 lines
Quoted 3 lines
In the meantime, would you mind adding a license to your code? If you have no preference, I like GPLv2-only, but it's your code, so whatever you like.
Done, GPLv2 it is.
Thanks!
thx,
Jason.
v2 cover impedance-matcher generic improvements
In reply to Daniel MackDaniel,
Here's a new version of my attempt to make this code generically useful. I've tested this on my dreamplug both using the commandline 'loadaddrs=appended,0x0700000' and appending all kirkwood*.dtb's.
It's still hacky and can't update the dtb yet. But it definitely works.
To make it work for the Raumfeld boards, you'll need to change board-raumfeld.c to use the proper compatible strings for the boards. Then, in the Makefile, change your uart address and MFG.
For folks interested in testing:
git://git.infradead.org/users/jcooper/impedance-matcher.git generic
btw - this is the first time I've needed to tinker with linker scripts, so if it looks wrong, please let me know!
thx,
Jason.
Jason Cooper (9):
add cscope Makefile target
separate common functions from board specific rename board.c to board-raumfeld.c s/.name/.compatible/
directly include needed headers
serial: split out 8250 code, configurable reg addr add generic board code
make appending images/dtbs optional appended dtbs works!
.gitignore | 2 +- Makefile | 59 +++++++++++++-------- append_dtbs.sh | 8 +++ atags.h | 10 ++++ board-dreamplug.c | 28 ++++++++++ board-generic.c | 39 ++++++++++++++ board-raumfeld.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ board.c | 88 -------------------------------- board.h | 10 ++-- dtbs.c | 36 +++++++++++++ dtbs.h | 6 +++ endian.h | 12 +++++ fdt.h | 64 +++++++++++++++++++++++ led.c | 54 -------------------- led.h | 6 --- main.c | 47 ++++++++--------- matcher.lds | 8 ++- print.c | 8 +-- print.h | 2 + register.c | 11 ++++ register.h | 9 ++++ serial-8250.c | 21 ++++++++ serial.h | 10 ++++ string.c | 99 +++++++++++++++++++++++++++++++++++ string.h | 9 ++++ types.h | 1 + 26 files changed, 590 insertions(+), 207 deletions(-) create mode 100755 append_dtbs.sh create mode 100644 board-dreamplug.c create mode 100644 board-generic.c create mode 100644 board-raumfeld.c delete mode 100644 board.c create mode 100644 dtbs.c create mode 100644 dtbs.h create mode 100644 endian.h create mode 100644 fdt.h delete mode 100644 led.c delete mode 100644 led.h create mode 100644 register.c create mode 100644 register.h create mode 100644 serial-8250.c create mode 100644 serial.h create mode 100644 string.c create mode 100644 string.h
Signature · 1 line
1.8.3.2
RFC PATCH v2 1/9 add cscope Makefile target
--- .gitignore | 1 + Makefile | 6 ++++++ 2 files changed, 7 insertions(+)
.gitignore +1 -0
@@ -1,6 +1,7 @@ *.sh *.o *.bin +cscope.* matcher uImage input/zImage
Makefile +6 -0
@@ -43,3 +43,9 @@ uImage: matcher.bin clean: rm -fr matcher.bin matcher *.o uImage +distclean: clean + rm -fr cscope.* + +cscope: + -find . -name "*.[chS]" >cscope.files + -cscope -b -R
Signature · 1 line
1.8.3.2
RFC PATCH v2 2/9 separate common functions from board specific
In reply to Jason Cooper--- Makefile | 7 +++++- board.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- board.h | 2 +- led.c | 54 ------------------------------------------- led.h | 6 ----- main.c | 27 ++++------------------ register.c | 11 +++++++++ register.h | 9 ++++++++ 8 files changed, 103 insertions(+), 90 deletions(-) delete mode 100644 led.c delete mode 100644 led.h create mode 100644 register.c create mode 100644 register.h
Makefile +6 -1
@@ -6,6 +6,11 @@ LD=$(CROSS_COMPILE)ld LOADADDR=0xa0008000 BINFMT=elf32-littlearm +COMMON_OBJS = \ + main.o \ + print.o \ + register.o + INPUT_OBJS = \ zimage.o \ dtb-raumfeld-controller-0.o \
@@ -29,7 +34,7 @@ zimage.o: input/zImage %.o: %.c $(GCC) $(CFLAGS) -c $^ -matcher: main.o print.o board.o led.o $(INPUT_OBJS) +matcher: $(COMMON_OBJS) board.o $(INPUT_OBJS) $(LD) $(LDFLAGS) -T matcher.lds -o $@ $^ matcher.bin: matcher
board.c +71 -6
90 lines not on this page · raw message
board.h +1 -1
@@ -8,6 +8,6 @@ struct board { const char *name; }; -struct board *match_board (__u32 machid,__u32 revision); +struct board *match_board (__u32 machid,const struct tag *);#endif
led.c deleted +0 -54
54 lines not on this page · raw message
led.h deleted +0 -6
@@ -1,6 +0,0 @@ -#ifndef _LED_H_ -#define _LED_H_ - -void led_panic (void ); - -#endif
main.c +5 -22
@@ -2,39 +2,22 @@#include "atags.h" #include "print.h" #include "board.h" -#include "led.h" extern __u32 _binary_input_zImage_start;void main (__u32 dummy,__u32 machid,const struct tag *tags) { -const struct tag *t;struct board *board; -__u32 system_rev =0 ;void (*start_kernel)(__u32 dummy,__u32 machid,void *dtb) = (void *) &_binary_input_zImage_start;putstr ("++ Impedance Matcher (3rd stage loader) ++\n" ); -/* walk the atags to determine the system revision */ -for_each_tag (t, tags) -switch (t->hdr.tag) { -case ATAG_REVISION : - system_rev = t->u.rev.rev; -break ; - } - - board =match_board (machid, system_rev &0xff ); -if (!board) { -putstr ("ERROR MATCHING BOARD!\n" ); -putstr ("MACHID: 0x" ); -printhex (machid); -putstr ("\n" ); -putstr ("SYSTEM_REV: 0x" ); -printhex (system_rev); -putstr ("\n" ); -led_panic (); - } +/* +* error resp. is board-specific, so won't return on error +* eg - raumfeld boards blink a led indefinitely +*/ + board =match_board (machid, tags);putstr ("Detected board: " );putstr (board->name);
register.c new file +11 -0
@@ -0,0 +1,11 @@ +#include "types.h" + +inline void writel (__u32 val,__u32 addr) +{ + *(volatile __u32 *) addr = val; +} + +inline __u32 readl (__u32 addr) +{ +return *(volatile __u32 *) addr; +}
register.h new file +9 -0
@@ -0,0 +1,9 @@ +#ifndef _REGISTER_H +#define _REGISTER_H + +#include "types.h" + +void writel (__u32 ,__u32 ); +__u32 readl (__u32 ); + +#endif
Signature · 1 line
1.8.3.2
RFC PATCH v2 3/9 rename board.c to board-raumfeld.c
In reply to Jason Cooper--- Makefile | 6 ++- board-raumfeld.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ board.c | 153 ------------------------------------------------------- 3 files changed, 158 insertions(+), 154 deletions(-) create mode 100644 board-raumfeld.c delete mode 100644 board.c
Makefile +5 -1
@@ -6,6 +6,10 @@ LD=$(CROSS_COMPILE)ld LOADADDR=0xa0008000 BINFMT=elf32-littlearm +MFG=raumfeld + +BOARD_OBJ = board-$(MFG).o + COMMON_OBJS = \ main.o \ print.o \
@@ -34,7 +38,7 @@ zimage.o: input/zImage %.o: %.c $(GCC) $(CFLAGS) -c $^ -matcher: $(COMMON_OBJS) board.o $(INPUT_OBJS) +matcher: $(COMMON_OBJS) $(BOARD_OBJ) $(INPUT_OBJS) $(LD) $(LDFLAGS) -T matcher.lds -o $@ $^ matcher.bin: matcher
board-raumfeld.c new file +153 -0
153 lines not on this page · raw message
board.c deleted +0 -153
153 lines not on this page · raw message
Signature · 1 line
1.8.3.2
RFC PATCH v2 4/9 s/.name/.compatible/
In reply to Jason Cooper--- board-raumfeld.c | 18 +++++++++--------- board.h | 2 +- main.c | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-)
board-raumfeld.c +9 -9
@@ -21,19 +21,19 @@ static struct board boards[] = { .machid = 2413, .system_rev = 0, .dtb = &_binary_input_raumfeld_controller_0_dtb_start, - .name = "Raumfeld Controller, revision 0", + .compatible = "Raumfeld Controller, revision 0", }, { .machid = 2413, .system_rev = 1, .dtb = &_binary_input_raumfeld_controller_1_dtb_start, - .name = "Raumfeld Controller, revision 1", + .compatible = "Raumfeld Controller, revision 1", }, { .machid = 2413, .system_rev = 2, .dtb = &_binary_input_raumfeld_controller_2_dtb_start, - .name = "Raumfeld Controller, revision 2", + .compatible = "Raumfeld Controller, revision 2", }, /* Controller */
@@ -41,19 +41,19 @@ static struct board boards[] = { .machid = 2414, .system_rev = 0, .dtb = &_binary_input_raumfeld_connector_0_dtb_start, - .name = "Raumfeld Connector, revision 0", + .compatible = "Raumfeld Connector, revision 0", }, { .machid = 2414, .system_rev = 1, .dtb = &_binary_input_raumfeld_connector_1_dtb_start, - .name = "Raumfeld Connector, revision 1", + .compatible = "Raumfeld Connector, revision 1", }, { .machid = 2414, .system_rev = 2, .dtb = &_binary_input_raumfeld_connector_2_dtb_start, - .name = "Raumfeld Connector, revision 2", + .compatible = "Raumfeld Connector, revision 2", }, /* Speaker */
@@ -61,19 +61,19 @@ static struct board boards[] = { .machid = 2415, .system_rev = 0, .dtb = &_binary_input_raumfeld_speaker_0_dtb_start, - .name = "Raumfeld Speaker, revision 0", + .compatible = "Raumfeld Speaker, revision 0", }, { .machid = 2415, .system_rev = 1, .dtb = &_binary_input_raumfeld_speaker_1_dtb_start, - .name = "Raumfeld Speaker, revision 1", + .compatible = "Raumfeld Speaker, revision 1", }, { .machid = 2415, .system_rev = 2, .dtb = &_binary_input_raumfeld_speaker_2_dtb_start, - .name = "Raumfeld Speaker, revision 2", + .compatible = "Raumfeld Speaker, revision 2", }, { 0, 0, NULL, NULL } /* sentinel */ };
board.h +1 -1
@@ -5,7 +5,7 @@ struct board {__u32 machid;__u32 system_rev;void *dtb; -const char *name; +const char *compatible; };struct board *match_board (__u32 machid,const struct tag *);
main.c +1 -1
@@ -20,7 +20,7 @@ void main(__u32 dummy, __u32 machid, const struct tag *tags) board =match_board (machid, tags);putstr ("Detected board: " ); -putstr (board->name); +putstr (board->compatible);putstr ("\n" );putstr ("Booting into Linux kernel ...\n" );
Signature · 1 line
1.8.3.2
RFC PATCH v2 4/9 s/.name/.compatible/
board-raumfeld.c static struct board boards[] = { · line 24
Quoted 10 lines · Jason Cooper
Signed-off-by Jason Cooper <[email protected]>board-raumfeld.c +1
-1@@ -21,19 +21,19 @@ static struct board boards[] = { .machid = 2413, .system_rev = 0, .dtb = &_binary_input_raumfeld_controller_0_dtb_start, - .name = "Raumfeld Controller, revision 0", + .compatible = "Raumfeld Controller, revision 0",
This looks a little unfortunate; those values don't look like they're the contents of the DT compatible property.
RFC PATCH v2 4/9 s/.name/.compatible/
Quoted 5 lines · Stephen Warren
Quoted 3 lines · Jason Cooper
Signed-off-by Jason Cooper <[email protected]>board-raumfeld.c +0
-0
Quoted 9 lines
board-raumfeld.c static struct board boards[] = { · line 24
Quoted 6 lines
board-raumfeld.c +1
-1@@ -21,19 +21,19 @@ static struct board boards[] = { .machid = 2413, .system_rev = 0, .dtb = &_binary_input_raumfeld_controller_0_dtb_start, - .name = "Raumfeld Controller, revision 0", + .compatible = "Raumfeld Controller, revision 0",This looks a little unfortunate; those values don't look like they're the contents of the DT compatible property.
Yes, this project is a week old. I figured a little volatility was allowed :-) Please see:
cb0088e board-raumfeld: tweak compatible strings
in:
https://github.com/zonque/pxa-impedance-matcher.git
I changed the api so that the user could link in a random number of dtbs _without_ hardcoding the addresses. Searching by the compatible string was the easiest way to accomplish this. Unfortunately, I didn't know his compatible strings when I made the change.
For the curious, the code that does this is here:
https://github.com/zonque/pxa-impedance-matcher/blob/master/dtbs.c
We plan to add dtb parsing in the future so that we can change the dtb based on the atags passed by the legacy bootloader.
thx,
Jason.
RFC PATCH v2 4/9 s/.name/.compatible/
Quoted 11 lines · Jason Cooper
I changed the api so that the user could link in a random number of dtbs _without_ hardcoding the addresses. Searching by the compatible string was the easiest way to accomplish this. Unfortunately, I didn't know his compatible strings when I made the change.
For the curious, the code that does this is here:
https://github.com/zonque/pxa-impedance-matcher/blob/master/dtbs.c
We plan to add dtb parsing in the future so that we can change the dtb based on the atags passed by the legacy bootloader.
... and then we can also specifically look into the compatible node of the dtb, and not just do a string search over the entire binary.
But for now, it's good enough.
Daniel
RFC PATCH v2 5/9 directly include needed headers
In reply to Jason Cooper--- atags.h | 2 ++ board.h | 3 +++ print.h | 2 ++ 3 files changed, 7 insertions(+)
atags.h +2 -0
@@ -1,6 +1,8 @@#ifndef _ATAG_H#define _ATAG_H +#include "types.h" +#define ATAG_NONE 0x00000000 struct tag_header {
board.h +3 -0
@@ -1,6 +1,9 @@ #ifndef _BOARD_H #define _BOARD_H +#include "types.h" +#include "atags.h" + struct board { __u32 machid; __u32 system_rev;
print.h +2 -0
@@ -1,6 +1,8 @@#ifndef _PRINT_H#define _PRINT_H +#include "types.h" +void putch (char c);void printhex (__u32 u);void putstr (const char *s);
Signature · 1 line
1.8.3.2
RFC PATCH v2 6/9 serial: split out 8250 code, configurable reg addr
In reply to Jason Cooper--- Makefile | 9 +++++++-- matcher.lds | 2 +- print.c | 8 +------- serial-8250.c | 21 +++++++++++++++++++++ serial.h | 10 ++++++++++ 5 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 serial-8250.c create mode 100644 serial.h
Makefile +7 -2
@@ -3,12 +3,17 @@ LDFLAGS=-static -nostdlib GCC=$(CROSS_COMPILE)gcc OBJCOPY=$(CROSS_COMPILE)objcopy LD=$(CROSS_COMPILE)ld -LOADADDR=0xa0008000 +LOADADDR=0x10008000 BINFMT=elf32-littlearm MFG=raumfeld +UART=8250 +UART_BASE=0xf1012000 + +CFLAGS+=-DUART_BASE=$(UART_BASE) BOARD_OBJ = board-$(MFG).o +UART_OBJ = serial-$(UART).o COMMON_OBJS = \ main.o \
@@ -38,7 +43,7 @@ zimage.o: input/zImage %.o: %.c $(GCC) $(CFLAGS) -c $^ -matcher: $(COMMON_OBJS) $(BOARD_OBJ) $(INPUT_OBJS) +matcher: $(COMMON_OBJS) $(BOARD_OBJ) $(UART_OBJ) $(INPUT_OBJS) $(LD) $(LDFLAGS) -T matcher.lds -o $@ $^ matcher.bin: matcher
matcher.lds +1 -1
@@ -1,5 +1,5 @@ SECTIONS { - . = 0xa0008000; + . = 0x10008000; .text : { * (.text); } .data : { * (.data); } .rodata : { * (.rodata); }
print.c +1 -7
@@ -1,5 +1,6 @@#include "types.h" #include "print.h" +#include "serial.h" static inline void nop (int n) {
@@ -7,12 +8,6 @@ static inline void nop(int n) asm("nop" ); } -static void __putch (char c) -{ - *(volatile __u32 *)0x40100000 = c; -nop (100 ); -} -void putch (char c) {__putch (c);
@@ -39,4 +34,3 @@ void putstr(const char *s)while (*s)putch (*s++); } -
serial-8250.c new file +21 -0
@@ -0,0 +1,21 @@ +#include "types.h" +#include "register.h" +#include "serial.h" + +/* +* Whole heartedly copied from barebox's mach-mvebu debug code. Thanks to +* Thomas Petazzoni for the original code. +*/ +void __putch (char c) +{ +/* Wait until there is space in the FIFO */ +while (!(readl (UART_BASE +UART_LSR ) &LSR_THRE )) + ; + +/* Send the character */ +writel (c,UART_BASE +UART_THR ); + +/* Wait to make sure it hits the line */ +while (!(readl (UART_BASE +UART_LSR ) &LSR_THRE )) + ; +}
serial.h new file +10 -0
@@ -0,0 +1,10 @@ +#ifndef _SERIAL_H +#define _SERIAL_H + +#define BIT (nr) (1UL << (nr)) +#define UART_THR 0x00 +#define UART_LSR 0x14 +#define LSR_THRE BIT(5) + +void __putch (char ); +#endif
Signature · 1 line
1.8.3.2
RFC PATCH v2 7/9 add generic board code
In reply to Jason Cooper--- Makefile | 3 +- atags.h | 8 ++++++ board-generic.c | 39 +++++++++++++++++++++++++ board.h | 1 + main.c | 5 +++- string.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ string.h | 8 ++++++ 7 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 board-generic.c create mode 100644 string.c create mode 100644 string.h
Makefile +2 -1
@@ -18,7 +18,8 @@ UART_OBJ = serial-$(UART).o COMMON_OBJS = \ main.o \ print.o \ - register.o + register.o \ + string.o INPUT_OBJS = \ zimage.o \
atags.h +8 -0
@@ -17,10 +17,18 @@ struct tag_revision {__u32 rev; }; +/* command line */ +#define ATAG_CMDLINE 0x54410009 + +struct tag_cmdline { +char cmdline[1 ];/* this is the minimum size */ +}; +struct tag {struct tag_header hdr;union {struct tag_revision rev; +struct tag_cmdline cmdline; } u; };
board-generic.c new file +39 -0
@@ -0,0 +1,39 @@ +#include "atags.h" +#include "board.h" +#include "print.h" +#include "types.h" +#include "string.h" + +struct board genboard; + +struct board *match_board (__u32 machid,const struct tag *tags) +{ +const struct tag *t; + +/* walk the atags to get the command line */ +for_each_tag (t, tags) +switch (t->hdr.tag) { +case ATAG_CMDLINE : +getaddrs (&genboard.kernel, &genboard.dtb, + t->u.cmdline.cmdline); +break ; + } + +if (genboard.kernel) { +putstr ("Kernel: 0x" ); +printhex ((__u32 )genboard.kernel); + }else +putstr ("Kernel: Appended" ); +putstr ("\n" ); + +if (genboard.dtb) { +putstr ("DTB: 0x" ); +printhex ((__u32 )genboard.dtb); + }else +putstr ("** DTB Not Found! **" ); +putstr ("\n" ); + + genboard.compatible =NULL ; + +return &genboard; +}
board.h +1 -0
@@ -8,6 +8,7 @@ struct board {__u32 machid;__u32 system_rev;void *dtb; +void *kernel;const char *compatible; };
main.c +4 -1
@@ -20,7 +20,10 @@ void main(__u32 dummy, __u32 machid, const struct tag *tags) board =match_board (machid, tags);putstr ("Detected board: " ); -putstr (board->compatible); +if (board->compatible) +putstr (board->compatible); +else +putstr ("Not given." );putstr ("\n" );putstr ("Booting into Linux kernel ...\n" );
string.c new file +89 -0
89 lines not on this page · raw message
string.h new file +8 -0
@@ -0,0 +1,8 @@ +#ifndef _STRING_H +#define _STRING_H + +int strncmp (const char *,const char *,int ); +void *gethexaddr (const char *,const char **); +int getaddrs (void **,void **,const char *); + +#endif
Signature · 1 line
1.8.3.2
RFC PATCH v2 8/9 make appending images/dtbs optional
In reply to Jason Cooper--- .gitignore | 1 - Makefile | 35 ++++++++++++++++------------------- append_dtbs.sh | 8 ++++++++ main.c | 15 +++++++++++++-- matcher.lds | 8 ++++++-- 5 files changed, 43 insertions(+), 24 deletions(-) create mode 100755 append_dtbs.sh
.gitignore +0 -1
@@ -1,4 +1,3 @@ -*.sh *.o *.bin cscope.*
Makefile +16 -19
@@ -1,4 +1,13 @@ -CFLAGS=-Wall -ffreestanding +ifneq ($(origin APPEND_KERNEL), undefined) +INPUT_OBJS=zimage.o +CFLAGS+=-DAPPEND_KERNEL="$(APPEND_KERNEL)" +endif + +ifneq ($(origin APPEND_DTBS), undefined) +CFLAGS+=-DAPPEND_DTBS="$(APPEND_DTBS)" +endif + +CFLAGS+=-Wall -ffreestanding LDFLAGS=-static -nostdlib GCC=$(CROSS_COMPILE)gcc OBJCOPY=$(CROSS_COMPILE)objcopy
@@ -21,34 +30,22 @@ COMMON_OBJS = \ register.o \ string.o -INPUT_OBJS = \ - zimage.o \ - dtb-raumfeld-controller-0.o \ - dtb-raumfeld-controller-1.o \ - dtb-raumfeld-controller-2.o \ - dtb-raumfeld-connector-0.o \ - dtb-raumfeld-connector-1.o \ - dtb-raumfeld-connector-2.o \ - dtb-raumfeld-speaker-0.o \ - dtb-raumfeld-speaker-1.o \ - dtb-raumfeld-speaker-2.o - all: uImage -dtb-%.o: input/%.dtb - $(OBJCOPY) -I binary -O $(BINFMT) -B arm $^ $@ - -zimage.o: input/zImage +zimage.o: $(APPEND_KERNEL) $(OBJCOPY) -I binary -O $(BINFMT) -B arm $^ $@ %.o: %.c $(GCC) $(CFLAGS) -c $^ matcher: $(COMMON_OBJS) $(BOARD_OBJ) $(UART_OBJ) $(INPUT_OBJS) - $(LD) $(LDFLAGS) -T matcher.lds -o $@ $^ + $(LD) $(LDFLAGS) -T matcher.lds -Ttext $(LOADADDR) -o $@ $^ matcher.bin: matcher - $(OBJCOPY) -O binary $^ $@ + $(OBJCOPY) -O binary --set-section-flags .bss=alloc,load,contents $^ $@ +ifneq ($(origin APPEND_DTBS), undefined) + ./append_dtbs.sh $@ $(APPEND_DTBS) +endif uImage: matcher.bin mkimage -A arm -O linux -C none -T kernel \
append_dtbs.sh new file +8 -0
@@ -0,0 +1,8 @@ +#!/bin/sh + +OUT="$1" +shift +DTBS="$*" + +cat $DTBS >>$OUT +dd if=/dev/zero of=$OUT oflag=append conv=notrunc bs=1 count=8 #sentinel
main.c +13 -2
@@ -3,13 +3,21 @@#include "print.h" #include "board.h" +#ifdef APPEND_KERNEL extern __u32 _binary_input_zImage_start; +#endif + +void main (__u32 dummy,__u32 machid,const struct tag *tags) + __attribute__((section (".text_main" )));void main (__u32 dummy,__u32 machid,const struct tag *tags) {struct board *board; -void (*start_kernel)(__u32 dummy,__u32 machid,void *dtb) = - (void *) &_binary_input_zImage_start; +void (*start_kernel)(__u32 dummy,__u32 machid,void *dtb); + +#ifdef APPEND_KERNEL + start_kernel = (void *) &_binary_input_zImage_start; +#endif putstr ("++ Impedance Matcher (3rd stage loader) ++\n" );
@@ -26,6 +34,9 @@ void main(__u32 dummy, __u32 machid, const struct tag *tags)putstr ("Not given." );putstr ("\n" ); +if (board->kernel) + start_kernel = board->kernel; +putstr ("Booting into Linux kernel ...\n" );start_kernel (0 ,0xffffffff , board->dtb); }
matcher.lds +6 -2
@@ -1,6 +1,10 @@ SECTIONS { - . = 0x10008000; - .text : { * (.text); } + .text : { * (.text_main); * (.text); } .data : { * (.data); } .rodata : { * (.rodata); } + .bss : + { + * (.bss); + } + PROVIDE (__end_of_image = .) ; }
Signature · 1 line
1.8.3.2
RFC PATCH v2 9/9 appended dtbs works!
In reply to Jason CooperWith this commit, the user can build a single binary with the zImage linked in and the dtbs appended.
The user needs to provide a board-*.c file, address of the uart, then:
make MFG=boardname APPEND_KERNEL=/tmp/zImage APPEND_DTBS=/tmp/*.dtb \
uImage
Look at board-raumfeld.c for an example of how to determine the board you are on and set the desired compatible string.
--- Makefile | 1 + board-dreamplug.c | 28 ++++++++++++++++++++++++ board-raumfeld.c | 49 ++++++++++++++++++++---------------------- board.h | 2 -- dtbs.c | 36 +++++++++++++++++++++++++++++++ dtbs.h | 6 ++++++ endian.h | 12 +++++++++++ fdt.h | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ string.c | 10 +++++++++ string.h | 1 + types.h | 1 + 11 files changed, 182 insertions(+), 28 deletions(-) create mode 100644 board-dreamplug.c create mode 100644 dtbs.c create mode 100644 dtbs.h create mode 100644 endian.h create mode 100644 fdt.h
Makefile +1 -0
@@ -25,6 +25,7 @@ BOARD_OBJ = board-$(MFG).o UART_OBJ = serial-$(UART).o COMMON_OBJS = \ + dtbs.o \ main.o \ print.o \ register.o \
board-dreamplug.c new file +28 -0
@@ -0,0 +1,28 @@ +#include "board.h" +#include "dtbs.h" +#include "print.h" +#include "register.h" +#include "types.h" + +/* +* this code is just a quick PoC for appending multiple dtbs. I don't have +* any boards handy with stock, non-DT bootloaders, so I have no machids to +* trigger off of. +*/ + +extern __u32 _binary_input_zImage_start; +extern __u32 __end_of_image; + +struct board board; +const char *compat ="globalscale,dreamplug" ; + +struct board *match_board (__u32 machid,const struct tag *tags) +{ + +/* testing zImage linked in and dtbs appended */ + board.kernel = &_binary_input_zImage_start; + board.compatible = compat; + board.dtb =find_dtb (&__end_of_image, compat); + +return &board; +}
board-raumfeld.c +23 -26
125 lines not on this page · raw message
board.h +0 -2
@@ -5,8 +5,6 @@#include "atags.h" struct board { -__u32 machid; -__u32 system_rev;void *dtb;void *kernel;const char *compatible;
dtbs.c new file +36 -0
@@ -0,0 +1,36 @@ +#include "endian.h" +#include "fdt.h" +#include "print.h" +#include "string.h" +#include "types.h" + +/* Yes, this is a dirty hack. But it's simple, and fast. */ + +int find_str (char *mem,__u32 memsz,const char *str) +{ +__u32 len =strlen (str); +const char *last = mem + memsz - len; +const char *p; + +for (p = mem; p < last; p++) { +if (*p == *str) +if (strncmp (p, str, len) ==0 ) +return 1 ; + } + +return 0 ; +} + +void *find_dtb (void *dtbs,const char *compat) +{ +struct fdt_header *d = (struct fdt_header *)dtbs; + +while (d->magic ==be_to_cpu (FDT_MAGIC )) { +if (find_str ((char *)d,be_to_cpu (d->totalsize), compat) ==1 ) +break ; + + d = (struct fdt_header *)((char *)d +be_to_cpu (d->totalsize)); + } + +return d; +}
dtbs.h new file +6 -0
@@ -0,0 +1,6 @@ +#ifndef _DTBS_H +#define _DTBS_H + +void *find_dtb (void *,const char *); + +#endif
endian.h new file +12 -0
@@ -0,0 +1,12 @@ +#ifndef _ENDIAN_H +#define _ENDIAN_H + +#include "types.h" + +#define be_to_cpu (x) \ + ( ((0xFF000000UL & ((__u32)x)) >> 24) | \ + ((0x00FF0000UL & ((__u32)x)) >> 8) | \ + ((0x0000FF00UL & ((__u32)x)) << 8) | \ + ((0x000000FFUL & ((__u32)x)) << 24) ) + +#endif
fdt.h new file +64 -0
64 lines not on this page · raw message
string.c +10 -0
@@ -7,6 +7,16 @@ int hexlut[1 + 'F' - '0'] = { 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* A - F */ }; +int strlen (const char *str) +{ +const char *c = str; + +while (*(c++)) + ; + +return c - str; +} +int strncmp (const char *stra,const char *strb,int len) {int diff=0 ;
string.h +1 -0
@@ -1,6 +1,7 @@#ifndef _STRING_H#define _STRING_H +int strlen (const char *);int strncmp (const char *,const char *,int );void *gethexaddr (const char *,const char **);int getaddrs (void **,void **,const char *);
types.h +1 -0
@@ -2,6 +2,7 @@#define _TYPES_Htypedef unsigned int __u32 ; +typedef unsigned long long __u64 ;#define NULL ((void *) 0)#endif /* _TYPES_H */
Signature · 1 line
1.8.3.2
RFC PATCH v2 9/9 appended dtbs works!
Quoted 2 lines · Jason Cooper
With this commit, the user can build a single binary with the zImage linked in and the dtbs appended.
Do you mean that you can append a DTB to the resulting binary we call the impedance matcher, or do you mean this supports the linking of a zImage with a DTB already appended?
If the later I'd recommend against
supporting this.
If the former that's fine.
This project allows for turning off CONFIG_ARM_APPENDED_DTB and that should probably be documented somewhere to avoid confusion.
Nicolas
RFC PATCH v2 9/9 appended dtbs works!
Quoted 7 lines · Nicolas Pitre
Quoted 2 lines · Jason Cooper
With this commit, the user can build a single binary with the zImage linked in and the dtbs appended.
Do you mean that you can append a DTB to the resulting binary we call the impedance matcher,
Yes.
Quoted 2 lines
This project allows for turning off
CONFIG_ARM_APPENDED_DTBand that should probably be documented somewhere to avoid confusion.
Agreed.
A lot of folks can just use the generic config without writing custom board code. So, appended or addressed zImage, and addressed single dtb. Once the impedance-matcher has some more real-world testing, should we look at deprecating CONFIG_ARM_APPENDED_DTB?
thx,
Jason.
RFC PATCH v2 9/9 appended dtbs works!
In reply to Nicolas PitreQuoted 2 lines · Nicolas Pitre
This project allows for turning off
CONFIG_ARM_APPENDED_DTBand that should probably be documented somewhere to avoid confusion.
Updated README.
thx,
Jason.
v2 cover impedance-matcher generic improvements
In reply to Jason CooperHi Jason,
Quoted 5 lines · Jason Cooper
Here's a new version of my attempt to make this code generically useful. I've tested this on my dreamplug both using the commandline 'loadaddrs=appended,0x0700000' and appending all kirkwood*.dtb's.
It's still hacky and can't update the dtb yet. But it definitely works.
Merged and pushed, thanks :)
Note the changes on top of yours though. it took me a while to figure out that my boards won't boots images that are concatinated to the finale image. I changed that back so that things are treated by objcopy, and now everything's fine.
Best regards,
Daniel
v2 cover impedance-matcher generic improvements
Daniel,
Quoted 7 lines · Daniel Mack
Hi Jason,
Quoted 4 lines · Jason Cooper
Here's a new version of my attempt to make this code generically useful. I've tested this on my dreamplug both using the commandline 'loadaddrs=appended,0x0700000' and appending all kirkwood*.dtb's.
Quoted 8 lines
Quoted 1 line
It's still hacky and can't update the dtb yet. But it definitely works.
Merged and pushed, thanks :)
Note the changes on top of yours though. it took me a while to figure out that my boards won't boots images that are concatinated to the finale image. I changed that back so that things are treated by objcopy, and now everything's fine.
Ok, that's probably cleaner anyway. I did get to learn more about linker scripts, so that was fun. :-)
I have one change to catch up to yours (replacing __end_of_image), plus I added versioning support for when you want to tag a release. Feel free to pull from:
git://git.infradead.org/users/jcooper/impedance-matcher.git dreamplug
thx,
Jason.
v2 cover impedance-matcher generic improvements
Quoted 5 lines · Jason Cooper
I have one change to catch up to yours (replacing
__end_of_image), plus I added versioning support for when you want to tag a release. Feel free to pull from:
git://git.infradead.org/users/jcooper/impedance-matcher.gitdreamplug
Done, thanks.
Am 04.07.2013 18:56, schrieb Daniel Mack:
Quoted 39 lines
Hi,
I'm facing a problem with a transition from legacy board-file driven ARM machines to DTB, and I'm under the impression that a solution for it could be of broader interest.
In short, devices that have been deployed in quantities come in three hardware variants, which all boot with a unique machine-id. We ship kernel images that have board support for all three machine types, and do minor fixups to platform data of some drivers at runtime, depending on the board revision number (passed in via ATAGs).
The built-in support for attaching a DTB to the zImage does not suffice here, because we have one image for all models, and also, we couldn't do a 'per-board-revision' selection that way either.
Unless I missed some recent discussion, this case is not easy to handle. Yes, I know that these kind of things should be handled by a next-generation bootloader, but in our case, we want to avoid a loader update of already shipped hardware by all means.
As a solution, I'm thinking of a small framework that could for example work as follows.
a) A small mechanism allows storing multiple DTB binary files inside the kernel binary at compile time, and a simple function can extract them again by name at runtime (something like what the firmware framework does, but I don't know if that one can be used at such an early stage in the boot process).
b) A DT_MACHINE_START-like macro takes both the machine ID and the name of a DTB file that is compiled in. When matched, generic functions would load the given file, populate the device tree and then conduct a generic DT boot for the specified platform.
c) Allow users to open-code the DTB lookup depending on whatever kind of runtime information (be it the
board_revisionor anything else).
Quoted 5 lines
Of course, everything has to be an opt-in that stubs itself out at zero costs if not needed.
I'm open to opinion and sugesstions :)
Depending on how different the board support for all your three machine types is, there might be an (of course unimplemented) option
d) have only one DTB file which contains all the information for your three machine types and then have a mechanism which selects ("activates") the entries valid for the board you boot based on some external information, e.g. the machine ID. I.e. you have one DTB file which contains alternative entries for the different boards. And which entry is used/activated is selected at (early) kernel runtime by the machine ID.
What I'm thinking about here is an extended version of the device tree overlays used (invented?) by the Beagle board community. They have a base device tree file and for their add on boards (capes) they load device tree overlay files based on an EEPROM ID read.
http://elinux.org/BeagleBone_and_the_3.8_Kernel#Cape_Manager_and_Device_Tree_Overlays
With this, they extend the device tree at runtime based on the attached extension boards.
Going one step further, having the alternative plugin/overlay definitions already in the initial DTB file and being able to select/activate single plugin/overlay definitions already in the early boot stage should give a general mechanism to support several, similar boards with slightly different configurations with one DTB.
Best regards
Dirk
On 07/04/2013 10:56 AM, Daniel Mack wrote:
...
Quoted 3 lines
The built-in support for attaching a DTB to the zImage does not suffice here, because we have one image for all models, and also, we couldn't do a 'per-board-revision' selection that way either.
...
Quoted 5 lines
As a solution, I'm thinking of a small framework that could for example work as follows.
a) A small mechanism allows storing multiple DTB binary files inside the kernel binary at compile time...
...
Quoted 2 lines
c) Allow users to open-code the DTB lookup depending on whatever kind of runtime information (be it the
board_revisionor anything else).
The problem with (c) is that in general it probably requires a lot of infra-structure to be working to implement it. On Tegra, the board revision is in an EEPROM attached to an I2C bus. You'd need to have parsed DT and started instantiating devices already before you could access the ID EEPROM to know which board revision you're running on. That's a bit of a chicked-and-egg problem. Even with a much simpler scheme such as board ID encoded into GPIOs, you'll still likely run into similar problems; pinmux and GPIO controller drivers are needed just to read the GPIOs, which then requires DT to instantiate those drivers.
So, the suggestion of Nicolas's that you mentioned does solve that rather neatly.