My Haiku ARM (UEFI) port progress

Recently I am working on making Haiku ARM port step progress. I am trying to use all my knowledge and experience about arm, because it’s China here, maybe I can’t report imediately.

Today After some debug about mmu and dcache and icache, I got our pl011 driver show some string. My work as below:

  1. Disable mmu and dcache & icache when platform init.

    status_t
    arch_platform_init(struct kernel_args *kernelArgs)
    {
    // NOTE: dprintf() is off-limits here, too early…

    mmu_disable();
    icache_disable();
    dcache_disable();
    return B_OK;
    }

  2. Some Hack to our pl011 driver when conscructing.

    void ArchUARTPL011::Init(addr_t base, int64 clock)
    {
    DebugUART::Init(base, clock);

    Enable();
    PutChar(‘H’);
    PutChar(‘A’);
    PutChar(’\n’);
    }

Now we could see the serial output “EA” .

Issues we have:

static char buffer[sizeof(ArchUARTPL011)];

ArchUARTPL011 *arch_get_uart_pl011(addr_t base, int64 clock)
{
   ArchUARTPL011 *uart = new(&buffer) ArchUARTPL011(base, clock);
   // the referrence to this instance will cause exception 
   uart->Init(base, clock);

when the issue happened, the uefi firmware will show message as below:

add-symbol-file /home/abuild/rpmbuild/BUILD/edk2-edk2-stable202102/Build/ArmVirtQemu-ARM/DEBUG_GCC5/ARM/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore/DEBUG/ArmPlatformPrePeiCore.dll 0x1220
add-symbol-file /home/abuild/rpmbuild/BUILD/edk2-edk2-stable202102/Build/ArmVirtQemu-ARM/DEBUG_GCC5/ARM/MdeModulePkg/Core/Pei/PeiMain/DEBUG/PeiCore.dll 0x5220
Register PPI Notify: DCD0BE23-9586-40F4-B643-06522CED4EDE
Install PPI: 8C8CE578-8A3D-4F1C-9935-896185C32DD3
Install PPI: 5473C07A-3DCB-4DCA-BD6F-1E9689E7349A
The 0th FV start address is 0x00000001000, size is 0x001FF000, handle is 0x1000
Register PPI Notify: 49EDB1C1-BF21-4761-BB12-EB0031AABB39
Register PPI Notify: EA7CA24B-DED5-4DAD-A389-BF827E8F9B38
Install PPI: B9E0ABFE-5979-4914-977F-6DEE78C278A6
Install PPI: DBE23AA9-A345-4B97-85B6-B226F1617389
Install PPI: 6847CC74-E9EC-4F8F-A29D-AB44E754A8FC
DiscoverPeimsAndOrderWithApriori(): Found 0x7 PEI FFS files in the 0th FV
Loading PEIM 9B3ADA4F-AE56-4C24-8DEA-F03B7558AE50
add-symbol-file /home/abuild/rpmbuild/BUILD/edk2-edk2-stable202102/Build/ArmVirtQemu-ARM/DEBUG_GCC5/ARM/MdeModulePkg/Universal/PCD/Pei/Pcd/DEBUG/PcdPeim.dll 0x1A220
Loading PEIM at 0x0000001A150 EntryPoint=0x0000001C675 PcdPeim.efi
Install PPI: 06E81C58-4AD7-44BC-8390-F10265F72480
Install PPI: 01F34D25-4DE2-23AD-3FF3-36353FF323F1
Install PPI: 4D8B155B-C059-4C8F-8926-06FD4331DB8A
Install PPI: A60C6B59-E459-425D-9C69-0BCC9CB27D81
Register PPI Notify: 605EA650-C65C-42E1-BA80-91A52AB618C6
Loading PEIM C61EF796-B50D-4F98-9F78-4F6F79D800D5
add-symbol-file /home/abuild/rpmbuild/BUILD/edk2-edk2-stable202102/Build/ArmVirtQemu-ARM/DEBUG_GCC5/ARM/ArmPlatformPkg/MemoryInitPei/MemoryInitPeim/DEBUG/MemoryInit.dll 0x13220
Loading PEIM at 0x00000013150 EntryPoint=0x000000142E5 MemoryInit.efi
QemuVirtMemInfoPeiLibConstructor: System RAM @ 0x40000000 - 0xBFFFFFFF
Memory Init PEIM Loaded
PeiInstallPeiMemory MemoryBegin 0xBC000000, MemoryLength 0x4000000
ArmVirtGetMemoryMap: Dumping System DRAM Memory Map:
	PhysicalBase: 0x40000000
	VirtualBase: 0x40000000
	Length: 0x80000000
DataAbort Exception at 0x9DA6
20 Likes

You can also see my implementation of software text mode over framebuffer: https://review.haiku-os.org/c/haiku/+/3882/1/src/system/boot/platform/riscv/console.cpp. It can be easily ported.

2 Likes

@X512 your console is really nice, and for arm platform, it’s nearly close for debug. :wink:

the only problem is why the reference to uart instance will break down.

I feel that working with bare virtual hardware is easier and productive than fightning with firmware.

I give an idea:

_start.S

.global _start
_start:
    ldr x5, =STACK_TOP
    mov sp,x5
    bl start
1:
    b 1b
.size _start, . - _start

start.c

#include <stdint.h>
#include <stddef.h>

#define UART0_BASE 0x09000000

void WriteChar(char ch)
{
	*(volatile uint32_t *)(UART0_BASE) = ch;
}

void WriteString(const char *str)
{
	for (const char *ch = str; *ch != '\0'; ch++)
		WriteChar(*ch);
}

void WriteLn()
{
	WriteChar('\n');
}

void WriteInt(int64_t val)
{
	if (val == -9223372036854775807LL - 1) WriteString("-9223372036854775808");
	else if (val < 0) {WriteString("-"); WriteInt(-val);}
	else {
		if (val > 9) WriteInt(val/10);
		WriteChar(val%10 + '0');
	}
}

void WriteHex(uint64_t val, int n)
{
	if (n > 1 || val > 0xf) WriteHex(val/0x10, n - 1);
	val = val%0x10;
	if (val <= 9) WriteChar(val + '0');
	else WriteChar(val - 10 + 'A');
}

void Recursion(int n)
{
	WriteString("+"); WriteInt(n); WriteLn();
	if (n > 0) Recursion(n - 1);
	WriteString("-"); WriteInt(n); WriteLn();
}

void start(void *fdt) {
	WriteString("This is a test\n");
	WriteString("123\n");

	WriteHex(0x12345678, 8); WriteLn();
	WriteHex(0x87654321, 8); WriteLn();
	WriteInt(-123456789); WriteLn();
	
	Recursion(4);

	WriteString("fdt: "); WriteHex((size_t)fdt, 8); WriteLn();
	WriteString("fdt[0]: "); WriteHex(*((uint32_t*)fdt + 0), 8); WriteLn();
	WriteString("fdt[1]: "); WriteHex(*((uint32_t*)fdt + 1), 8); WriteLn();

	for (;;) {}
}

linker.ld

ENTRY(_start)
 
SECTIONS {
   . = 0x40000000;
 
    /* Make sure our entry stub goes first */
    .stub   : { _start.o(.text) }
    .text   : { *(.text) }
    .rodata : { *(.rodata) }
    .data   : { *(.data) }
    .bss    : { *(.bss COMMON) }
 
    STACK_BASE = .;
    . += 0x10000;
    STACK_TOP = .;
}

Build with following commands:

clang --target=aarch64-linux-gnu -ffreestanding -fpic -c _start.S
clang --target=aarch64-linux-gnu -ffreestanding -fpic -c start.c
ld.lld -T linker.ld _start.o start.o -o start
llvm-objcopy -O binary start start.bin

Run with:

qemu-system-aarch64 -M virt -cpu cortex-a57 -kernel start.bin -nographic

Output:

This is a test
123
12345678
87654321
-123456789
+4
+3
+2
+1
+0
-0
-1
-2
-3
-4
fdt: 44000000
fdt[0]: EDFE0DD0
fdt[1]: 00001000

All operations can be done from Haiku.

10 Likes

After the previous hacking, I found the code blow will have different results

// we can only display 'H' char.
int32 ii = 0;
char gd[20] = "HACB\n";
while (ii<6) {
    arch_debug_serial_putchar(gd[ii]);
    ii++;
}

// we will got all char displayed.
ii = 0;
char gc[20] = {‘H’, ‘A’, ‘C’, ‘B’, ‘\n’};
while (ii<6) {
arch_debug_serial_putchar(gc[ii]);
ii++;
}

All the difference of upper code is where we put the string:

  1. “HACB” will be packed to bss field or data field?
  2. the array will be filled in function processed.

I wonder there is something wrong with kernel.ld, or missed parsing elf in efi loader.

1 Like

Do you run this code in kernel, not haiku_loader? I had similar issue. -fpic -shared is needed for compiling kernel. You can disassemble kernel binary and look how constants and global variables are compiled. Also take a look at relocations. Check that required relocations are implemented here.

2 Likes

Yes, these code is running in kernel mode, I am not sure what’s the problem, although it will break when accessing static struct variable .

As you can see, ELF relocations are currently not implemented for ARM64, you need to implement it. Sorry, if you are working on 32 bit ARM, relocation resolving is here.

1 Like

it’s arm 32bit, but it can’t explain. I am not very familiar with elf referring things. :frowning:

Can you upload kernel binary somewhere so it contains writing of string constant data, so I can analyze it?

1 Like

The test kernel binary is https://github.com/pengphei/haiku-arm-binary/blob/main/kernel_arm

kernel_arm have no relocations and use absolute addressing with load address 0x80000000. Is it really loaded at 0x80000000?

I missed something, I forget to recover the kernel link script.

This kernel_arm binary (provided by) is linked with the kernel.ld from riscv64 :frowning: I will rebuild another with it’s original kernel.ld .

Also where your test code is located? In _start or in some other function?

I have update the hack code to github https://github.com/pengphei/haiku/commit/02800c9edd80fc41ddcc75fdf9612aa4733af58f

1 Like

how are things progressing? :slight_smile:

1 Like

Have you you switsh to ARM now? :wink:

Not yet. Posted to wrong topic.

2 Likes

I have tried use -fpic and -fshared to build arm kernel, but bootloader will parse kernel fail with “Couldn’t found both text and data segment”.

2 Likes

On other architectures there were some problems with the kernel linker scripts. The bootloader expects the text and data sections to be each in a separate segment, but some of the linker scripts are not doing this correctly.

I think you can compare the linker script with other architectures and see if the segments are defined correctly.

3 Likes