What is the process for generating a bare metal binary with MSVC tools?
In GNU land, you cc
compile or as
assemble the sources into object files, ld
link the object files into an ELF (with a linker script) and then objcopy
the relevant sections out of the ELF as a "firmware binary". I want to do the same thing, but only using MSVC provided tools.
I've been testing with the following ARM64 startup.s
:
AREA .text, CODE, READONLY
start
LDR w1, =0xDEADBEEF
B .
END
This is suppose to simply load the lower 32 bits of the X1 register with 0xDEADBEEF and then spin. To assemble the code I run:
armasm64.exe startup.s
I'm guessing that if I had a peripherals.c
source file, I'd need to link startup.s
and peripherals.c
into a single executable file (COFF?, PE?). Finally, I'd need to strip the any COFF/PE headers so that an ARM MCU can execute the code when loaded.
Disclaimer: I am not within my area of expertise here, and I am proposing an answer based on some tests I did using the MSVC tools, after reading some Microsoft documentation, and three days after the question was asked with no answers having be proposed yet. I hope this answer will trigger more informed answers, so that I may gladly retract it.
The answer to the question "What is the process for generating a bare metal binary with MSVC tools?" is likely: "There is none".
aarch64-pe.asm
:
AREA .text, CODE, READONLY
EXPORT start
start
LDR w1, =0xDEADBEEF
B .
END
(The symbol 'start' needs to be made public using the EXPORT
directive in order to be resolved by the linker).
Assembling:
armasm64.exe aarch64-pe.asm
Now, the linker for aarch64 (version 14.28.29334.0) does for example only support a limited list of target subsystems:
BOOT_APPLICATION,
CONSOLE,
WINDOWS,
NATIVE,
POSIX,
EFI_APPLICATION, EFI_BOOT_SERVICE_DRIVER, EFI_ROM, EFI_RUNTIME_DRIVER
From the Microsoft and EFI documentation, it seems all those subsystems require a loader capable of understanding the PECOFF
format or to be able to run into the BCD WMI Provider
environment in the case of the BOOT_APPLICATION
subsystem.
There is no such thing as a "BAREMETAL" subsystem.
When attempting to link aarch64-pe.obj for each of the subsystems but EFI_ROM
using 0x0000000040000000
as the base address, the linker exited displaying the same error, complaining that the start address could not be less than 4GiB:
D:\opt\msvc\arm64>for %I in (BOOT_APPLICATION CONSOLE WINDOWS NATIVE POSIX EFI_APPLICATION EFI_BOOT_SERVICE_DRIVER EFI_ROM EFI_RUNTIME_DRIVER) do link /entry:start /BASE:0x0000000040000000 /subsystem:%I aarch64-pe.obj
D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:BOOT_APPLICATION aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation. All rights reserved.
LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB
D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:CONSOLE aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation. All rights reserved.
LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB
D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:WINDOWS aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation. All rights reserved.
LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB
D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:NATIVE aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation. All rights reserved.
LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB
D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:POSIX aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation. All rights reserved.
LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB
D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:EFI_APPLICATION aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation. All rights reserved.
LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB
D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:EFI_BOOT_SERVICE_DRIVER aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation. All rights reserved.
LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB
D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:EFI_ROM aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation. All rights reserved.
LINK : warning LNK4075: ignoring '/BASE' due to '/SUBSYSTEM:EFI_ROM' specification
D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:EFI_RUNTIME_DRIVER aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation. All rights reserved.
LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB
This is likely an issue for a bare-metal embedded system, or may this require an MMU to be available and already configured by a ... bare-metal program starting with the MMU disabled from a start address less than 4GiB.
When running dumpbin.exe
against aarch64-pe.efi, the base address seemed to be set to 0000000180000000
since the ldr
instruction was located at 0x0000000180001000
, and the file type was set to DLL
.
dumpbin.exe /disasm aarch64-pe.efi
File Type: DLL
0000000180001000: 18000041 ldr w1,0000000180001008
0000000180001004: 14000000 b 0000000180001004
0000000180001008: DEADBEEF
Summary
1000 .rdata
1000 .text
When executing dumpbin.exe
against the executables produced by the linker with 0x0000000100000000
as the base address, the file type was consistantly EXECUTABLE IMAGE
.
Even more, dumpbin.exe
does not seem to offer converting the resulting executable into a standard format such as s-record
or intel hex
either.
My conclusion would therefore be that the MSVC tools alone do not allow building aarch64 bare-metal applications for the time beeing.
User contributions licensed under CC BY-SA 3.0