On 19/11/2013 10:51, Sascha Hauer wrote: > On Mon, Nov 18, 2013 at 11:25:27AM +0100, Mathieu Anquetin wrote: >> Hi, >> >> I am currently trying to port Barebox to a new ARM-based machine and I >> am facing some questions concerning low level initialization (before >> relocation to RAM). Reading the header files, I came across 3 functions >> that may be of interest during startup but I can't find an example of >> them being called, they are : >> - board_init >> - dram_init >> - board_init_lowlevel > Ok, let's take this opportunity to write it up: > > Generally we have two different startup mechanisms. The first, simpler > version is without pbl image. Here the very first instruction executed > is the function in the text_entry section: > > ./arch/arm/cpu/start.c:125:void __naked __section(.text_entry) start(void) > > This calls barebox_arm_head() which is a static inline assembly > function. This function builds an ARM reset vector table. It also > switches the CPU to Thumb2 mode if necessary. The next step is to jump > to barebox_arm_reset_vector: > > ./arch/arm/include/asm/barebox-arm-head.h:58: "b barebox_arm_reset_vector\n" > > barebox_arm_reset_vector is a board specific function you have to > implement. Depending on your SoC and bootmode this function will run > from internal SRAM, SDRAM or maybe NOR flash. Your job here is to > initialize your SDRAM, see for example > ./arch/arm/boards/eukrea_cpuimx35/lowlevel.c. At the end of this > function jump to: > > void __noreturn barebox_arm_entry(uint32_t membase, uint32_t memsize, uint32_t boarddata); > > Pass this function the start of your SDRAM and the size. The third value > is a value that will be preserved and can be retrieved later from board > code. barebox_arm_entry is the common entry point for all ARM boards, > This function will move the barebox binary to it's final address, clear > the bss segment and jump to start_barebox() which is the common > architecture independent entry point. > > /* ------------------------------------- */ > > The above is the 'traditional' way. Next we have PBL > (CONFIG_PBL_IMAGE=y) which was introduced for compressed images. Here > two binaries are created, one 'real' image which gets compressed and one > uncompressor image (the PBL). For board code it makes no difference. > Boards still implement barebox_arm_reset_vector to setup their SDRAM and > in the end jump to barebox_arm_entry(). The difference is that both the > board code and barebox_arm_entry() end up in the decompressor image. The > 'real' image does not contain any lowlevel code, instead it starts at: > > ./arch/arm/cpu/start.c:160:void __naked __section(.text_entry) start(uint32_t membase, uint32_t memsize, uint32_t boarddata) > > /* ------------------------------------- */ > > Finally we have multiimage support (CONFIG_PBL_MULTI_IMAGES=y) which is > a variant of the PBL. With multiimage support we have three binaries > involved: Again one 'real' binary, one decompressor, and one out of > multiple Board specific binaries. The board specific binary is for a > single board only and starts with ENTRY_FUNCTION(). This function will > be the very first code executed. It's job is again to setup SDRAM and > jump to barebox_arm_entry(). With multiimage support barebox_arm_entry > will simply jump past the current image which will be where the > decompressor code is. > > > So whatever you do you have to implement barebox_arm_reset_vector() or > define an ENTRY_FUNCTION(). Both functions should assume that they are > executed at another place they are linked at. This means that you can't > use global variables. Newer gcc versions also seem to make > problems with switch/case. > > > This is no direct answer to your question, but I hope it contains the > answers you were looking for ;) If not feel free to ask. > > Sascha > Very nice and detailed explanation of the boot process implementation ! Now I see more clearly which function is called and when during the startup code. Concerning the three functions I mentioned, it makes it clear for me that they are just prototypes that I can implement for naming clarity and I should not worry of them being called elsewhere in the code. Then, just to make sure, before calling a new function from the barebox_arm_reset_vector, do I have to call arm_setup_stack beforehand ? Or is it just for functions that have a return value and/or arguments ? (I never called functions where runtime and linking addresses differ... C has given me bad habits ;) ) Thanks again for your answer, -- *Mathieu ANQUETIN* /Software Engineer / Logo CAHORS Mail CRDE ZI des Grands Camps 46090 MERCUES Tél. : +33 (0)5 65 30 38 27 *www.groupe-cahors.com* *GROUPE CAHORS soutient le pacte mondial.* _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox