[edk2-devel] ArmVirt and Self-Updating Code

Ard Biesheuvel ardb at kernel.org
Fri Jul 23 10:13:10 UTC 2021


On Fri, 23 Jul 2021 at 11:55, Marvin Häuser <mhaeuser at posteo.de> wrote:
>
> On 22.07.21 17:14, Ard Biesheuvel wrote:
> > On Thu, 22 Jul 2021 at 16:54, Bret Barkelew<Bret.Barkelew at microsoft.com>  wrote:
> >> Expanding audience to the full dev list…
> >>
> >> See below…
> >>
> >>
> >>
> >> - Bret
> >>
> >>
> >>
> >> From: Thomas Abraham
> >> Sent: Wednesday, July 7, 2021 11:07 PM
> >> To: Bret Barkelew; Ard Biesheuvel (TianoCore); Lindholm, Leif; Laszlo Ersek; Marvin Häuser; Sami Mujawar
> >> Cc: nd
> >> Subject: [EXTERNAL] RE: ArmVirt and Self-Updating Code
> >>
> >>
> >>
> >> + Sami
> >>
> >>
> >>
> >> From: Bret Barkelew<Bret.Barkelew at microsoft.com>
> >> Sent: Thursday, July 8, 2021 11:05 AM
> >> To: Thomas Abraham<thomas.abraham at arm.com>; Ard Biesheuvel (TianoCore)<ardb+tianocore at kernel.org>; Lindholm, Leif<leif at nuviainc.com>; Laszlo Ersek<lersek at redhat.com>; Marvin Häuser<mhaeuser at posteo.de>
> >> Subject: ArmVirt and Self-Updating Code
> >>
> >>
> >>
> >> All,
> >>
> >>
> >>
> >> Marvin asked me a question on the UEFI Talkbox Discord that’s a little beyond my ken…
> >>
> >>
> >>
> >> “There is self-relocating code in ArmVirtPkg:
> >>
> >> https://github.com/tianocore/edk2/blob/17143c4837393d42c484b42d1789b85b2cff1aaf/ArmVirtPkg/PrePi/PrePi.c#L133-L165
> >>
> >> According to comments in the ASM, it seems like this is for Linux-based RAM boot (I saw further stuff for KVM, so it makes sense I guess?). It seems unfortunate it cannot be mapped into a known address range so that self-relocation is not necessary, but that's out of my scope to understand.
> >>
> > "Mapping" implies that the MMU is on, but this code boots with the MMU
> > off. Unlike x86, ARM does not define any physical address ranges that
> > are guaranteed to be backed by DRAM, so a portable image either needs
> > to be fully position independent, or carry the metadata it needs to
> > relocate itself as it is invoked.
>
> And I understood it right that the idea is to use "-fpie" to
> 1) have all control flow instructions be position-independent (i.e.
> jumps, calls, etc; ARM docs don't spill it out, but vaguely imply this
> always is possible?), and

The primary reason to use -fpie and PIE linking is to ensure that the
resulting ELF executable contains a RELA section that describes every
location in the binary where a memory address is stored that needs to
be updated according to the actual placement in memory. The side
effect of -fpie is that position independent global references are
emitted (i.e., ADRP/ADD instructions which are relative to the program
counter). However, the AArch64 compiler uses those by default anyway,
so for this it is not strictly needed.

> 2) emit a GOT, which ends up being converted to PE/COFF Relocations (->
> self-relocation), for global data that cannot be referenced relatively?
> Is there any way to know/force that no symbol in GOT is accessed up
> until the end of the self-relocation process?
>

It is not really a GOT. Actually, a GOT is undesirable, as it forces
global variables to be referenced via an absolute address, even when a
relative reference could be used.

For instance, a statically initialized pointer always carries an
absolute address, and so it always needs an entry in the RELA table

E.g.,

int foo = 10; // external linkage
static int *bar = &foo;

In this case, there is no way to use relative addressing because the
address of foo is taken at build time.

However, if bar would be something like

static int *bar() { return &foo; }

the address is only taken at runtime, and the compiler can use a
relative reference instead, and no RELA entry is needed. With a GOT,
we force the compiler to allocate a variable that holds the absolute
address, which we would prefer to avoid.

> >> “Now, StandaloneMmPkg has similar (self-)relocation code too:https://github.com/tianocore/edk2/blob/17143c4837393d42c484b42d1789b85b2cff1aaf/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c#L379-L386
> >>
> >> Because I cannot find such elsewhere, I assume it must be for the same ARM virtualised environment as above.
> > No.
> >
> >> The binary it applies the Relocations to is documented to be the Standalone MM core, but in fact SecCore is located:
> >>
> >> https://github.com/tianocore/edk2/blob/17143c4837393d42c484b42d1789b85b2cff1aaf/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c#L131-L158
>
> As per your comments below, I think SecCore should not be located here.
> Is the Standalone MM core of *type* SecCore in the FFS (without *being*
> SecCore)? This confused me the most.
>

If the FFS SecCore section type is used here, it does not mean that
the image is a SEC image in the strict PI sense.

Perhaps we were just too lazy to add a new type to the FFS spec?

> >> “This yields the following questions to me:
> >>
> >> 1) What even invokes Standalone MM on ARM? It is documented it is spawned during SEC, but I could not find any actual invocation.
> >>
> > It is not spawned by the normal world code that runs UEFI. It is a
> > secure world component that runs in a completely different execution
> > context (TrustZone). The code does run with the MMU enabled from the
> > start, but running from an a priori fixed offset was considered to be
> > a security hazard, so we added self relocation support.
> >
> > The alternative would have been to add metadata to the StMmCore
> > component that can be interpreted by the secure world component that
> > loads it, but this would go beyond any existing specs, and make
> > portability more problematic.
> >
> >> 2) Why does Standalone MM (self-)relocation locate SecCore? Should it not already have been relocated with the code from ArmPlatformPkg? Is Standalone MM embedded into ARM SecCore?
> >>
> > No and no. Standalone MM has nothing to do with the code that runs as
> > part of UEFI itself. ArmPlatformPkg is completely separate from
> > StandaloneMmPkg.
> >
> >> 3) Why is SecCore the only module relocated? Are all others guaranteed to be "properly" loaded?
> >>
> > SecCore contains a PE/COFF loader, so all subsequent modules are
> > loaded normally. This is similar to the ArmVirtQemuKernel
> > self-relocating SEC module, which only relocates itself in this
> > manner, and relies on standard PE/COFF metadata for loading other
> > modules.
>
> Interesting... this definitely is vastly different from the x86 side of
> things. I think most things became very clear. Thanks a lot!
>
> >> 4) Is there maybe some high-level documented about the ARM boot flow? It seems to be significantly different from the x86 routes quite vastly.”
> >>
> > trustedfirmware.org may have some useful documentation.
>
> I'll check it some time, hopefully this weekend. Thanks!
>

My pleasure.


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#78128): https://edk2.groups.io/g/devel/message/78128
Mute This Topic: https://groups.io/mt/84380729/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-






More information about the edk2-devel-archive mailing list