diff options
author | Maximilian Brune <maximilian.brune@9elements.com> | 2023-07-08 18:15:28 +0200 |
---|---|---|
committer | Martin L Roth <gaumless@gmail.com> | 2023-09-05 16:08:42 +0000 |
commit | 7285c375fca1e16a9dececd375e5a3853a222042 (patch) | |
tree | 93ee492d61a02f8f49e8e144abd7a2cafa9e11de | |
parent | c5c293cad118b4ef62a63e966701e04f2e0ebc04 (diff) |
Documentation/rmodules.md: Add rmodule Documentation
Signed-off-by: Maximilian Brune <maximilian.brune@9elements.com>
Change-Id: I97cd3030cd660a86295257caf723c9f517bed146
Reviewed-on: https://review.coreboot.org/c/coreboot/+/76383
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin L Roth <gaumless@gmail.com>
-rw-r--r-- | Documentation/rmodules.md | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/Documentation/rmodules.md b/Documentation/rmodules.md new file mode 100644 index 0000000000..520d184ddc --- /dev/null +++ b/Documentation/rmodules.md @@ -0,0 +1,81 @@ +# Relocatable Modules (rmodules) + +Relocatable modules are currently only used on x86. Relocatable +modules are executables. Exectuables which can be executed anywhere in +memory. Anywhere means that the module does not need to be executed +at a defined memory address which is known at build/link time. For +coreboot stages like bootblock and romstage it is known at build +time at which addresses they are executed. For some exectuables it +is however not known at which specific address they are executed in +runtime (for example postcar and ramstage). Relocateable modules +usually allocate the space for the modules just before they are +supposed to be executed. After enough space is allocated, CBMEM will +return the location of the allocated space. Now the relocation can be +done by fixing up all relocation entries in the relocatable module +based on the location of the binary (which was returned by CBMEM +at runtime). + +# Implementation Details + +## build time + +At build time the rmodtool (util/cbfstool/rmodtool.c) is used to +create relocatable modules. The rmodtool basically takes an ELF +file as an input and writes an ELF as output. It basically does +a simple conversion from one ELF file to another slighty changed +ELF file. First the tool makes sure that the ELF file fits a few +requirements. For example there can only be one segment (loadable +program header) in the input ELF file. After that it goes through +the ELF relocation table and takes any entry that applies to the one +segment we want to load at runtime. The rmodtool will then write all +these relocation entires in a new ELF section called ".reloc". After +that the ELF relocation table will be cleared. + +One can split the rmodules in two different kinds: +1. coreboot stages (postcar, ramstage) +2. simple binaries (smm, smmstub, sipi\_vector) + +They are actually handled the same by the build system and only differ +in the fact, that they are either coreboot stages or they are not. + +In the end the ELF files will have three different ELF sections, +which are all created by the rmodtool. +1. relocation header (.header) +2. program (.program) +3. relocation entries (.relocs) + +## runtime + +Either rmodule\_load (lib/rmodule.c) is used directly or through the +rmodule\_stage\_load (lib/rmodule.c) wrapper. It is used to load the +stages (postcar and ramstage) or small programs like (sipi\_vector, +smm, smmstub) into memory before jumping to them. In the case of a +coreboot stage, CBMEM is used to allocate space for the stage in memory +via the rmodule\_cbfs\_allocater (lib/rmodule.c). At this point the +location of the stage in memory is known and all relocation (address +fixups) need to be done now. This is basically just a simple loop that +goes through each relocation entry. Each relocation entry is just an +address pointing to a location that needs relocation. The relocation +itself is just a simple addition, that adds an offset from where the +image was "supposed" to be at link time, to where it is now relocated. + +## module\_parameters + +module\_parameters is a section inside the rmodule ELF file. Its +basically a way to pass runtime information to an rmodule +before jumping to it. The caller will use rmodule\_parameters() +(lib/rmodule.c) to get the runtime address of the module\_parameters +and the callee (the rmodule itself) usually appends the section to +specific types via compiler attributes. For example: +``` +static const +volatile __attribute((aligned(4), __section__(".module_parameters"))) +struct smm_runtime smm_runtime; +``` + +# x86 why rmodules +//TODO +x86: postcar and ramstage cannot conflict with payload regarding +memory placement. Therefore payload location is usually fixed and +postcar/ramstage can be placed at a location in memory that is +figured out at runtime. |