Den 2023-02-13 kl. 15:11, skrev Nick Clifton: > Hi Ulf, > >>> From the sound of what you have written below it would be >>> easier to use the assembler to create the header > >> One of the problems is time of build. >> The header should contain the time when things are linked together, >> not when things are compiled. >> >> Another is that one of the fields is the size of the application >> which is only known at link time. >> >> Doing things in the linker seems to be the cleanest way. >> >> We would probably have the header is in a separate file which is >> included in the linker script. > > If you need to compute information in the header based upon the > actual linked executable then you will not be able to do so from > inside a linker script.  (Well not without modifying the linker, > and I am trying to avoid that). > > But - what you can do is post-process the linked file to extract > the information you want, create a separate file containing the > header constructed from this information, and then insert the > header into the executable, without relinking it.  (I am thinking > of objcopy's --add-section command line option here). > > Alternatively you could link with a dummy header that is basically > empty and then use a tool like GNU Poke[1] to insert the necessary > bytes and strings afterwards. This is what a typical header looks like: header:            QUAD(TAG1)                            // 0 ECC:    QUAD(ECC(SYNDROME, START_OF_ECC, .end_of_text))     // 8 START_OFF_ECC: BUILDTIME:             QUAD(SECONDS_SINCE_1970)               // 16 ENTRY: LONG(program_entry)                 // 24 SIZE:   LONG(.end_of_text - .start_of_text)                 // 28            BYTE(VERSION1)                         // 32            BYTE(VERSION2)                         // 33            BYTE(VERSION3)                         // 34            BYTE(VERSION3)                         // 35            LONG(0)                             // 36            LONG(0)                             // 40            LONG(0)                             // 44 APPLICATION:            ASCII    16, "MyApp"                          // 48            ASCII    32, "A special app"                        // 64            ASCII    32, "With Info"                            // 96 HELP            ASCII    120 "No help available"                     // 120            QUAD(TAG2)                          // 248 Total Size = 265 byte Most of the header info is part of the linker file. The linker needs to compute:    ECC:    BUILDTIME:    ENTRY:    SIZE: === We already discussed ideas for ECC. For buildtime, we currently added an include file which we create during the linking process. To have a BUILDTIME directive that generates a 64-bit word with "seconds since 1970-01-01 00:00" does not seem to be very difficult - at least on linux. Parse the call and get the |__time64_t |seconds from the OS. ENTRY and SIZE is supported right now in the linker. Best Regards Ulf Samuelsson > > [1] http://www.jemarch.net/poke > > >> Assume you have the following flash sectors. >> >> * 64kB (65536 bytes) >> * 64kB (65536 bytes) >> * 128kB >> * n x 256kB >> >> The bootloader resides in the first 64 kB sector and the application >> starts in the second 64kB sector. >> >> If the application <= 65536 bytes, the section should be 64kB and >> should be filled with a FILL value >> >> If the application is 65540 bytes, the section should be 64kB+128kB >> and should be filled with a FILL value > > Ah yes.  This is a known problem for the linker.  It does not have a > mechanism > to distribute section(s) across multiple memory regions, using one > until it is full > and then switching to another. I don't think we need to distribute sections amongs multiple regions. I just need to say that the PC should be aligned to the next 64kB boundary and it should be filled with my fill value. Then I need to check the PC and if it is not at the end of a flash segment, I want to add an additional BYTE(0xFF) and again align to the next segment. The following would handle application up to 512kB.     . = ALIGN(64kB) if (. == 0x30000)     BYTE(0xFF)     . = ALIGN(64kB) end if if (. == 0x50000)     BYTE(0xFF)     . = ALIGN(64kB) end if if (. == 0x60000)     BYTE(0xFF)     . = ALIGN(64kB) end if if (. == 0x70000)     BYTE(0xFF)     . = ALIGN(64kB) end if > > I am sorry, but I do not have an easy workaround for you.  If you are > able to try > multiple links, you could start with one that just uses the smallest > memory configuration > first, and if that fails move up to bigger configurations, possibly > with different > assignments of sections to memory regions afterwards. > > >> Would you consider adding ielftools to binutils? > > I would prefer to leave it as a separate project for now.  I am worried > about bringing in a tool that will only be of use to a very small > audience > (maybe just you ?) and having to maintain it.  Of course if you can > persuade > more people to request that the sources be integrated then I can take > abother > look at the issue... > >> Note that if the linker can call an external tool to compute the CRC >> based on the extracted text segment, and insert that into the >> resulting ELF file. >> then this is superior to running a utility afterwards. > > Actually -- there might be a way to do this: A linker plugin.  The > linker already > has the architecture to support plugins, and you could create a new > one which would > scan the text section, compute a CRC and then insert the value into a > header in the > linked image... > OK, tell me more! > Cheers >   Nick > >