Recent

Author Topic: Does anyone know how to pass parameters to loaded elf files in uefi bare metal?  (Read 628 times)

TYDQ

  • Full Member
  • ***
  • Posts: 102
I was attemptting to pass parameter to loaded elf files in uefi bare metal,my uefi loader is compiled in PEcoff format and can be loaded by uefi firmware and my kernel is compiled in elf format to be loaded by my uefi loader.I was trying very hard to pass the parameter to enter the kernel,but I failed to do it and my kernel crashed because the parameter does not transmit properly.
my uefi loader code is:
Code: Pascal  [Select][+][-]
  1. program uefiloader;
  2.  
  3. {$MODE FPC}
  4.  
  5. uses uefi,tydqfs,binarybase,bootconfig;
  6.  
  7. var proccontent:array[1..67108864] of byte;
  8.     procsize:dword;
  9.    
  10. function efi_main(ImageHandle:efi_handle;systemtable:Pefi_system_table):efi_status;[public,alias:'_mainCRTStartup'];
  11. var {For checking elf file}
  12.     fsi:tydqfs_system_info;
  13.     edl:efi_disk_list;
  14.     sfsp:Pefi_simple_file_system_protocol;
  15.     fp:Pefi_file_protocol;
  16.     efsl:efi_file_system_list;
  17.     i,count:natuint;
  18.     status:efi_status;
  19.     finfo:efi_file_info;
  20.     finfosize:natuint;
  21.     procsize:natuint;
  22.     partstr:PWideChar;
  23.     gpl:efi_graphics_list;
  24.     isgraphics:boolean;
  25.     loaderscreenconfig:screen_config;
  26.     {For elf structure}
  27.     header:elf64_header;
  28.     program_headers:^elf64_program_header;
  29.     LowAddress,HighAddress:qword;
  30.     PageCount:qword;
  31.     KernelRelocateBase:qword;
  32.     RelocateOffset:qword;
  33.     ZeroStart:^qword;
  34.     SourceStart,DestStart:^byte;
  35.     KernelEntry:Pointer;
  36.     bool:array[1..4] of boolean;
  37.     {For loading elf files}
  38.     initparam:Psys_parameter_item;
  39.     param:sys_parameter;
  40.     func:sys_parameter_function;
  41.     funcandparam:sys_parameter_function_and_parameter;
  42.     res:Pointer;
  43. begin  
  44.  {Initialize the uefi loader}
  45.  compheap_initialize; sysheap_initialize;
  46.  efi_console_initialize(systemtable,efi_bck_black,efi_lightgrey,500);
  47.  efi_console_enable_mouse_blink(systemtable,false,0);
  48.  edl:=efi_disk_tydq_get_fs_list(systemtable);
  49.  fsi:=tydq_fs_systeminfo_read(edl);
  50.  freemem(edl.disk_block_content); freemem(edl.disk_content); edl.disk_count:=0;
  51.  efsl:=efi_list_all_file_system(systemtable,0);
  52.  i:=1; count:=efsl.file_system_count;
  53.  gpl:=efi_graphics_initialize(systemtable);
  54.  efi_graphics_get_maxwidth_maxheight_and_maxdepth(gpl,1);
  55.  {Detect the kernel file}
  56.  while(i<=count) do
  57.   begin
  58.    sfsp:=(efsl.file_system_content+i-1)^;
  59.    sfsp^.OpenVolume(sfsp,fp);
  60.    fp^.Open(fp,fp,'\EFI\SYSTEM\kernelmain.elf',efi_file_mode_read,efi_file_system);
  61.    fp^.SetPosition(fp,0);
  62.    finfosize:=sizeof(efi_file_info);
  63.    fp^.GetInfo(fp,@efi_file_info_id,finfosize,finfo);
  64.    procsize:=finfo.filesize;
  65.    status:=fp^.efiRead(fp,procsize,proccontent);
  66.    if(status=efi_success) then break;
  67.   end;
  68.  if(i>count) then
  69.   begin
  70.    efi_console_output_string(systemtable,'Boot failed,the kernel does not exist.'#10);
  71.    while(True) do;
  72.   end;
  73.  {Initialize the kernel parameter}
  74.  loaderscreenconfig.screen_is_graphics:=fsi.header.tydqgraphics;
  75.  loaderscreenconfig.screen_address:=(gpl.graphics_item^)^.Mode^.FrameBufferBase;
  76.  loaderscreenconfig.screen_width:=(gpl.graphics_item^)^.Mode^.Info^.HorizontalResolution;
  77.  loaderscreenconfig.screen_height:=(gpl.graphics_item^)^.Mode^.Info^.VerticalResolution;
  78.  {Free the system heap}
  79.  freemem(gpl.graphics_item); gpl.graphics_count:=0;
  80.  freemem(efsl.file_system_content); efsl.file_system_count:=0;
  81.  {Check the elf kernel}
  82.  bool[1]:=Pelf64_header(@proccontent)^.elf64_identify[1]=Byte(#$7F);
  83.  bool[2]:=Pelf64_header(@proccontent)^.elf64_identify[2]=Byte('E');
  84.  bool[3]:=Pelf64_header(@proccontent)^.elf64_identify[3]=Byte('L');
  85.  bool[4]:=Pelf64_header(@proccontent)^.elf64_identify[4]=Byte('F');
  86.  if not(bool[1] and bool[2] and bool[3] and bool[4]) then
  87.   begin
  88.    efi_console_output_string(systemtable,'Boot failed,the kernel is not the elf format file.'#10);
  89.    while(True) do;
  90.   end;
  91.  bool[1]:=Pelf64_header(@proccontent)^.elf64_identify[5]=Byte(#$2);
  92.  if(bool[1]=false) then
  93.   begin
  94.    efi_console_output_string(systemtable,'Boot failed,the kernel is not the elf 64-bit format file.'#10);
  95.    while(True) do;
  96.   end;
  97.  {Load the elf kernel}
  98.  header:=Pelf64_header(@proccontent)^;
  99.  program_headers:=@proccontent+header.elf64_program_header_offset;
  100.  LowAddress:=$FFFFFFFFFFFFFFFF; HighAddress:=0;
  101.  for i:=1 to header.elf64_program_header_number do
  102.   begin
  103.    if((program_headers+i-1)^.program_type=elf_program_table_load) then
  104.     begin
  105.      if(LowAddress>(program_headers+i-1)^.program_physical_address) then
  106.       begin
  107.        LowAddress:=(program_headers+i-1)^.program_physical_address;
  108.       end;
  109.      if(HighAddress<(program_headers+i-1)^.program_physical_address+(program_headers+i-1)^.program_memory_size) then
  110.       begin
  111.        HighAddress:=(program_headers+i-1)^.program_physical_address+(program_headers+i-1)^.program_memory_size;
  112.       end;
  113.     end;
  114.   end;
  115.  PageCount:=(HighAddress-LowAddress) shr 12+1;
  116.  SystemTable^.BootServices^.AllocatePages(AllocateAnyPages,efiLoaderCode,PageCount,KernelRelocateBase);
  117.  RelocateOffset:=kernelRelocateBase-LowAddress;
  118.  Zerostart:=Pointer(KernelRelocateBase);
  119.  for i:=1 to PageCount shl 9 do
  120.   begin
  121.    (Zerostart+i-1)^:=$0000000000000000;
  122.   end;
  123.  for i:=1 to header.elf64_program_header_number do
  124.   begin
  125.    if((program_headers+i-1)^.program_type=elf_program_table_load) then
  126.     begin
  127.      SourceStart:=Pointer(@proccontent+(program_headers+i-1)^.program_offset);
  128.      DestStart:=Pointer((program_headers+i-1)^.program_virtual_address+RelocateOffset);
  129.      Move(DestStart^,SourceStart^,(program_headers+i-1)^.program_file_size);
  130.     end;
  131.   end;
  132.  KernelEntry:=Pointer(header.elf64_entry+RelocateOffset);
  133.  efi_console_enable_mouse_blink(systemtable,false,0);
  134.  {Set the parameter for kernel}
  135.  initparam:=allocmem(sizeof(sys_parameter_item));
  136.  initparam^.item_content:=@loaderscreenconfig;
  137.  initparam^.item_size:=sizeof(screen_config);
  138.  param:=sys_parameter_construct(initparam,1);
  139.  {Execute the elf file}
  140.  func.func:=sys_function(KernelEntry);
  141.  funcandparam:=sys_parameter_and_function_construct(param,func,sizeof(return_config));
  142.  partstr:=UintToWhex(Qword(@funcandparam.parameter_parameter));
  143.  efi_console_output_string(systemtable,partstr);
  144.  efi_console_output_string(systemtable,#10);
  145.  Wstrfree(partstr);
  146.  res:=sys_parameter_function_execute(funcandparam);
  147.  {Free the memory}
  148.  sys_parameter_and_function_free(funcandparam);
  149.  SystemTable^.BootServices^.FreePages(KernelRelocateBase,PageCount);
  150.  while True do;
  151.  efi_main:=efi_success;
  152. end;
  153.  
  154. begin
  155. end.
my kernel is:
Code: Pascal  [Select][+][-]
  1. program kernelmain;
  2.  
  3. {$MODE FPC}
  4.  
  5. uses bootconfig,graphics;
  6.  
  7. function kernel_main(param:sys_parameter):Pointer;[public,alias:'_start'];
  8. var screenconfig:screen_config;
  9.     ptr:Pgraphics_item;
  10.     res:Preturn_config;
  11. begin
  12.  {$ifdef cpux86_64}
  13.  screenconfig:=Pscreen_config(Psys_parameter($BFEC1900)^.param_content)^;
  14.  {$else cpux86_64}
  15.  screenconfig:=Pscreen_config(param.param_content)^;
  16.  {$endif}
  17.  graphics_heap_initialize;
  18.  ptr:=graphics_heap_getmem(1,1,screenconfig.screen_width,screenconfig.screen_height);
  19.  graphics_draw_block(ptr,1,1,screenconfig.screen_width,screenconfig.screen_height,$FF,$FF,$FF,$FF);
  20.  graphics_heap_output_to_screen(screenconfig.screen_address,screenconfig.screen_width,screenconfig.screen_height);
  21.  res:=allocmem(sizeof(return_config));
  22.  res^.content:=screenconfig.screen_address;
  23.  res^.size:=screenconfig.screen_width;
  24.  res^.count:=screenconfig.screen_height;
  25.  kernel_main:=res;
  26. end;
  27.  
  28. begin
  29. end.
Does anyone have the idea about this?I am solved this problem by visit constant address's data and read the data in this address(not pass parameter from uefi loader).However,there MUST be a better solution to pass parameter correctly.If the constant address in uefi changes,the data read will be a failure.
To look for used unit in my pascal code,You can go to my Github to https://github.com/TYDQSoft/UEFIPascalOS for used units.

bytebites

  • Hero Member
  • *****
  • Posts: 674
Yes someone knows
« Reply #1 on: August 07, 2024, 06:43:57 pm »
Quote
Does anyone know
Off topic note,  quoted text redundant info. Thank you for your patience.

TYDQ

  • Full Member
  • ***
  • Posts: 102
Re: Yes someone knows
« Reply #2 on: August 08, 2024, 02:15:41 am »
Quote
Does anyone know
Off topic note,  quoted text redundant info. Thank you for your patience.
Have you reply to the wrong topic?

 

TinyPortal © 2005-2018