flat assembler
Message board for the users of flat assembler.

Index > Main > Call C function from PE64 EFI boot loader?

Author
Thread Post new topic Reply to topic
robstat7



Joined: 03 Apr 2024
Posts: 4
robstat7 03 Apr 2024, 10:21
Hello,

I am creating a UEFI boot loader which is of format PE64 EFI and I am trying to call my kernel's main (C) function, kernel_main, from it. It is a very basic function at the moment defined in kernel.c file.

Code:
extrn  _kernel_main    

After defining the above external symbol in the boot loader, on assembling it, I get the illegal instruction error.

I searched in the FASM programmer's manual and also over the internet for using the extrn directive in PE output format but did not find any. Any idea?


Last edited by robstat7 on 04 Apr 2024, 08:30; edited 1 time in total
Post 03 Apr 2024, 10:21
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 04 Apr 2024, 04:39
extrn is for use with object files. Is your kernel not a PE file?

Perhaps try: https://gitlab.com/bztsrc/easyboot
Post 04 Apr 2024, 04:39
View user's profile Send private message Visit poster's website Reply with quote
robstat7



Joined: 03 Apr 2024
Posts: 4
robstat7 04 Apr 2024, 08:40
bitRAKE wrote:
extrn is for use with object files. Is your kernel not a PE file?


Sorry, my bad. I've fixed the subject of the thread and also updated the details. I'm compiling kernel.c using gcc to kernel.o and assembling my boot loader using fasm.



Thanks but I'm writing my own boot loader Smile
Post 04 Apr 2024, 08:40
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 04 Apr 2024, 09:01
Code:
format MS64 COFF
; they can have the same name using the simpler syntax
extrn the_kernel as "_kernel_main"

; they can have the same name using the simpler syntax
public main as "main_entry"
main:
        jmp the_kernel    
... just make sure the linker knows the entry symbol name.
Post 04 Apr 2024, 09:01
View user's profile Send private message Visit poster's website Reply with quote
robstat7



Joined: 03 Apr 2024
Posts: 4
robstat7 04 Apr 2024, 10:50
format MS64 COFF is not a PE output format! UEFI firmware needs an image with a PE32+ format.
Post 04 Apr 2024, 10:50
View user's profile Send private message Reply with quote
MatQuasar



Joined: 25 Oct 2023
Posts: 105
MatQuasar 04 Apr 2024, 10:56
Last time I had similar experience, I link my bootloader to Pascal kernel entrypoint:
Code:
format binary as 'img'
org 7C00h

extrn '_kmain' as kmain

use16

start:
.....
.....
        


And I got error:
Code:
extrn '_kmain' as kmain
processed: extrn '_kmain' as kmain
error: illegal instruction.    


This is reply from admin @revolution at the time:
revolution wrote:
Binary format doesn't have any export table to define external names, so fasm can't define any extrn label.

You'll need to supply the raw address where kmain is loaded. Usually the boot sector loads in other sectors to a known address and jmps to the first instruction. Similar to how the first post in this thread shows.


But I ended up using NASM instead of FASM to compile the source file.
Post 04 Apr 2024, 10:56
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20430
Location: In your JS exploiting you and your system
revolution 04 Apr 2024, 11:22
MatQuasar: For UEFI the boot loader is not the same as the BIOS boot sector.

UEFI uses a PE executable format.

To the OP: you can use a linker to make your final boot loader PE file. Use the COFF format as shown above and link it to your C output to create the EFI file.
Post 04 Apr 2024, 11:22
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 04 Apr 2024, 19:05
robstat7 wrote:
format MS64 COFF is not a PE output format! UEFI firmware needs an image with a PE32+ format.
Then what format is your kernel in? Are you designing a custom object format? Do you seek the challenge of writing an ELF loader? If not then just have GCC output a COFF object and link it to your loader.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 04 Apr 2024, 19:05
View user's profile Send private message Visit poster's website Reply with quote
robstat7



Joined: 03 Apr 2024
Posts: 4
robstat7 05 Apr 2024, 08:54
revolution wrote:
To the OP: you can use a linker to make your final boot loader PE file. Use the COFF format as shown above and link it to your C output to create the EFI file.


Hello. My boot loader is not working. It is exiting after displaying a blank screen for a moment. Here is my boot.asm:
Code:
; Boot Loader written in FASM
struc UINT32 {
        align 4
        . dd ?
}

struc void {
        align 8
        . dq ?
}

macro struct name {
        virtual at 0
                name name
        end virtual
}

struc EFI_TABLE_HEADER {
        .Signature              void
        .Revision               UINT32
        .HeaderSize             UINT32
        .CRC32                  UINT32
        .Reserved               UINT32
}
struct EFI_TABLE_HEADER

struc EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
        .Reset                  void
        .OutputString           void
        .TestString             void
        .QueryMode              void
        .SetMode                void
        .SetAttribute           void
        .ClearScreen            void
        .SetCursorPosition      void
        .EnableCursor           void
        .Mode                   void
}
struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL

struc EFI_SYSTEM_TABLE {
        .Hdr                    EFI_TABLE_HEADER
        .FirmwareVendor         void
        .FirmwareRevision       UINT32
        .ConsoleInHandle        void
        .ConIn                  void
        .ConsoleOutHandle       void
        .ConOut                 void
        .StandardErrorHandle    void
        .StdErr                 void
        .RuntimeServices        void
        .BootServices           void
        .NumberOfTableEntries   void
        .ConfigurationTable     void
}
struct EFI_SYSTEM_TABLE

; format PE64 EFI
format MS64 COFF

extrn kernel_main

;entry start
public start

section '.bss' data readable writeable align 16
        align 16
        stack_bottom:
                rb 4096 
        stack_top:

section '.text' code executable readable

start:
        ; store the image handle and the system table pointer passed by the firmware
        mov [ImageHandle], rcx
        mov [SystemTable], rdx

        mov rsp, stack_top

        ; call kernel_main
        jmp kernel_main

        ; hang here
        jmp $

section '.data' data readable writeable

ImageHandle   dq ?
SystemTable   dq ?
    


kernel.c:
Code:
void kernel_main(void)
{
        int a;
        int b;

        a = 10;
        b = a;
        b = b * 10;
}
    


linker.ld
Code:
/* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(start)
SECTIONS
{
  . = 0;
  ImageBase = .;
  /* .hash and/or .gnu.hash MUST come first! */
  .hash : { *(.hash) }
  .gnu.hash : { *(.gnu.hash) }
  . = ALIGN(4096);
  .eh_frame : { *(.eh_frame) }
  .gcc_except_table : { *(.gcc_except_table*) }
  . = ALIGN(4096);
  .text :
  {
   _text = .;
   *(.text)
   *(.text.*)
   *(.gnu.linkonce.t.*)
   *(.plt)
   . = ALIGN(16);
  }
  _etext = .;
  _text_size = _etext - _text;
  . = ALIGN(4096);
  .reloc :
  {
   KEEP (*(.reloc))
  }

  . = ALIGN(4096);
  .data :
  {
   _data = .;
   *(.got.plt)
   *(.got)
   *(.data*)
   *(.sdata)

   /*
    * Note that these aren't the using the GNU "CONSTRUCTOR" output section
    * command, so they don't start with a size.  Because of p2align and the
    * end/END definitions, and the fact that they're mergeable, they can also
    * have NULLs which aren't guaranteed to be at the end.
    */
   . = ALIGN(16);
   __init_array_start = .;
   *(SORT(.init_array.*))
   *(.init_array)
   __init_array_end = .;
  . = ALIGN(16);
   __CTOR_LIST__ = .;
   *(SORT(.ctors.*))
   *(.ctors)
   __CTOR_END__ = .;
  . = ALIGN(16);
   __DTOR_LIST__ = .;
   *(SORT(.dtors.*))
   *(.dtors)
   __DTOR_END__ = .;
   . = ALIGN(16);
   __fini_array_start = .;
   *(SORT(.fini_array.*))
   *(.fini_array)
   __fini_array_end = .;

   /* the EFI loader doesn't seem to like a .bss section, so we stick
      it all into .data: */
   *(.sbss)
   *(.scommon)
   *(.dynbss)
   *(.bss*)
   *(COMMON)
   *(.rel.local)
  }
  .note.gnu.build-id : { *(.note.gnu.build-id) }

  _edata = .;
  _data_size = _edata - _etext;
  . = ALIGN(4096);
  .dynamic  : { *(.dynamic) }
  . = ALIGN(4096);
  .rela :
  {
    *(.rela.text*)
    *(.rela.data*)
    *(.rela.got)
    *(.rela.dyn)
    *(.rela.stab)
    *(.rela.init_array*)
    *(.rela.fini_array*)
    *(.rela.ctors*)
    *(.rela.dtors*)
  }
  . = ALIGN(4096);
  .rela.plt : { *(.rela.plt) }
  . = ALIGN(4096);
  .rodata : { *(.rodata*) }
  . = ALIGN(4096);
  .dynsym   : { *(.dynsym) }
  . = ALIGN(4096);
  .dynstr   : { *(.dynstr) }
  . = ALIGN(4096);
  .ignored.reloc :
  {
    *(.rela.reloc)
    *(.note.GNU-stack)
  }
  .comment 0 : { *(.comment) }
}
    


Commands to build the EFI file:
Code:
$ fasm boot.asm build/boot.o
$ gcc -c kernel.c -o build/kernel.o
$ ld -shared -Bsymbolic -T linker.ld build/boot.o build/kernel.o -o build/system.so
ld: warning: build/boot.o: missing .note.GNU-stack section implies executable stack
ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker
$ objcopy -j .text -j .sdata -j .data -j .rodata -j .dynamic -j .dynsym  -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc --target efi-app-x86_64 --subsystem=10 build/system.so build/BOOTx64.EFI
$ file build/BOOTx64.EFI 
build/BOOTx64.EFI: PE32+ executable (EFI application) x86-64 (stripped to external PDB), for MS Windows, 4 sections
    
Post 05 Apr 2024, 08:54
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.