我的OS工程在UEFIPascalOS: UEFI Pascal OS(基于UEFI的Pascal写的操作系统)的源码仓库,现在仅作为展示使用,作为爱好项目,没有实际用途 (gitee.com)里面,我是为了解决这个问题,所以把这个链接放出来让大家看看我的源代码并进行改进。
我重新修改了我的UEFIPascalOS的elf2efi,发现了新的问题,如下所示:
我的UEFI应用无法获取简单文件系统协议的对象,继而无法获取iso光盘里面的\EFI\System\kernelmain.elf导致启动失败,显示为
Welcome to TYDQ bootloader!
Boot failed,the kernel does not exist.
不知道是不是实际上龙芯UEFI文件系统协议的接口和其他架构的不大一样还是我的代码有问题,我的相关代码如下:
program uefiloader;
{$MODE FPC}
uses uefi,binarybase,bootconfig,graphics;
function efi_main(ImageHandle:efi_handle;systemtable:Pefi_system_table):efi_status;{$ifdef cpux86_64}MS_ABI_Default;{$endif}{$ifdef cpui386}cdecl;{$endif}[public,alias:'_start'];
var {For checking elf file}
sfsp:Pefi_simple_file_system_protocol;
fp:Pefi_file_protocol;
efsl:efi_file_system_list;
i,j,count,procindex:natuint;
status:efi_status;
finfo:efi_file_info;
finfosize:natuint;
proccontent:Pointer;
procsize:natuint;
partstr:PWideChar;
gpl:efi_graphics_list;
isgraphics:boolean;
loaderscreenconfig:screen_config;
{For elf structure}
header:elf64_header;
program_headers:^elf64_program_header;
LowAddress,HighAddress:qword;
PageCount:qword;
KernelRelocateBase:qword;
RelocateOffset:qword;
ZeroStart:^qword;
SourceStart,DestStart:^byte;
KernelEntry:Pointer;
bool:array[1..4] of boolean;
{For loading elf files}
initparam:Psys_parameter_item;
param:sys_parameter;
func:sys_parameter_function;
funcandparam:sys_parameter_function_and_parameter;
res:Pointer;
{For memory initializtion}
memorymap:efi_memory_map;
memoryavailable:efi_memory_result;
addressoffset:natuint;
allocaddress:natuint;
begin
{Initialize uefi environment}
efi_initialize(ImageHandle,systemtable);
{Initialize the uefi loader}
efi_console_initialize(efi_bck_black,efi_lightgrey,0);
efsl:=efi_list_all_file_system(2);
i:=0; count:=efsl.file_system_count;
efi_console_output_string('Welcome to TYDQ bootloader!'#10);
{Detect the kernel file}
while(i<=count) do
begin
inc(i);
if(i>count) then break;
sfsp:=(efsl.file_system_content+i-1)^;
sfsp^.OpenVolume(sfsp,fp);
status:=fp^.Open(fp,fp,'\EFI\SYSTEM\kernelmain.elf',efi_file_mode_read,0);
if(status<>efi_success) then continue;
finfosize:=sizeof(efi_file_info);
fp^.GetInfo(fp,@efi_file_info_id,finfosize,finfo);
procsize:=finfo.FileSize;
fp^.SetPosition(fp,0);
proccontent:=efi_allocmem(procsize);
for j:=1 to procsize do
begin
procindex:=1;
fp^.efiRead(fp,procindex,(proccontent+j-1)^);
end;
fp^.Close(fp);
if(status=efi_success) then break;
end;
if(i>count) then
begin
efi_console_output_string('Boot failed,the kernel does not exist.'#10);
while(True) do;
end;
这里还有代码,这是获取文件系统对象的:
function efi_list_all_file_system(isreadonly:byte):efi_file_system_list;[public,alias:'EFI_LIST_ALL_FILE_SYSTEM'];
var totalnum,i:natuint;
totalbuf:Pefi_handle;
sfsp:Pefi_simple_file_system_protocol;
fsinfo:efi_file_system_info;
fp:Pefi_file_protocol;
data:efi_file_system_list;
realsize:natuint;
begin
GlobalSystemTable^.BootServices^.LocateHandleBuffer(ByProtocol,@efi_simple_file_system_protocol_guid,nil,totalnum,totalbuf);
data.file_system_content:=efi_allocmem(totalnum*sizeof(Pointer)); data.file_system_count:=0;
for i:=1 to totalnum do
begin
GlobalSystemTable^.BootServices^.HandleProtocol((totalbuf+i-1)^,@efi_simple_file_system_protocol_guid,sfsp);
sfsp^.OpenVolume(sfsp,fp);
realsize:=sizeof(efi_file_system_info);
fp^.GetInfo(fp,@efi_file_system_info_id,realsize,fsinfo);
if(isreadonly=1) and (fsinfo.ReadOnly=true) then
begin
inc(data.file_system_count);
(data.file_system_content+data.file_system_count-1)^:=sfsp;
end
else if(isreadonly=0) and (fsinfo.ReadOnly=false) then
begin
inc(data.file_system_count);
(data.file_system_content+data.file_system_count-1)^:=sfsp;
end
else if(isreadonly>=2) then
begin
inc(data.file_system_count);
(data.file_system_content+data.file_system_count-1)^:=sfsp;
end;
end;
efi_list_all_file_system:=data;
end;
其他的比如说结构体和另外的代码放不下,只能直接去看顶上的链接来看看我的源代码以发现问题。