diff options
author | olivier <olivier@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2017-08-17 22:12:55 +0000 |
---|---|---|
committer | olivier <olivier@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2017-08-17 22:12:55 +0000 |
commit | 88416976a5cfcb9c906143929e9924a1679186b6 (patch) | |
tree | 85da27a40986f98ca939eb5a803c755d0cebe9d3 | |
parent | 34dcf3d87263d3169a38d07c97417763c7bdccac (diff) | |
download | fpc-88416976a5cfcb9c906143929e9924a1679186b6.tar.gz |
* Some more UEFI declarations and debugging stuff.
Most notably, there is now an example of a call to HandleProtocol to get
an interface (EFI_LOADED_IMAGE) and then retrieve informations from there
like the ImageBase and ImageSize of our binary. It might be usefull for
debugging in the future...
This is a common way to get things done with the UEFI API, as far as i know.
git-svn-id: https://svn.freepascal.org/svn/fpc/branches/olivier@36933 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r-- | uefi/rtl/uefi/system.pp | 272 |
1 files changed, 242 insertions, 30 deletions
diff --git a/uefi/rtl/uefi/system.pp b/uefi/rtl/uefi/system.pp index 49e518e062..9dc3158e64 100644 --- a/uefi/rtl/uefi/system.pp +++ b/uefi/rtl/uefi/system.pp @@ -16,7 +16,10 @@ unit System; interface +{ $define USE_NOTHREADMANAGER} {$define DISABLE_NO_THREAD_MANAGER} + +{ $define FPC_HEAPTRC_EXTRA} { include system-independent routine headers } {$I systemh.inc} @@ -61,15 +64,70 @@ const { Basic EFI definitions } -{$IFDEF FPC} -{$PACKRECORDS C} -{$ENDIF} const EFI_SYSTEM_TABLE_SIGNATURE = $5453595320494249; EFI_RUNTIME_SERVICES_SIGNATURE = $56524553544e5552; EFI_BOOT_SERVICES_SIGNATURE = $56524553544f4f42; +type + { } + { A GUID } + { } +// Still does not understand why it does not correspond yet... +(* EFI_GUID = packed record + Data1 : UINT32; + Data2 : UINT16; + Data3 : UINT16; + Data4 : array[0..7] of UINT8; + end; +*) +// Until then, we use this definition under Freepascal. +// Don't forget to reverse data in integer definition (to take endianess into account) + EFI_GUID = packed record + Data : array[0..15] of UINT8; + end; + + +{$IFDEF FPC} +{$PACKRECORDS C} +{$ENDIF} + +const +// Many attends at understanding the binary representation of a GUID. + +// Image handle +//#define LOADED_IMAGE_PROTOCOL \ +// { 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} } + +// UEFI.inc : EFI_LOADED_IMAGE_PROTOCOL_UUID equ 0A1h,31h,1bh,5bh,62h,95h,0d2h,11h,8Eh,3Fh,0h,0A0h,0C9h,69h,72h,3Bh + +// LOADED_IMAGE_PROTOCOL : EFI_GUID = (Data1:$5B1BB31A1; Data2:$9562; +// Data3:$11D2; Data4: ($8E, $3F, $00, $A0, $C9, $69, $72, $3B)); + +// LOADED_IMAGE_PROTOCOL : EFI_GUID = (Data1:$A1311B5B; Data2:$6295; +// Data3:$D211; Data4: ($8E, $3F, $00, $A0, $C9, $69, $72, $3B)); + +// Good definition ! + LOADED_IMAGE_PROTOCOL : EFI_GUID = (Data: ( $A1, $31, $1B, $5B, $62, $95, + $D2, $11, $8E, $3F, $00, $A0, $C9, $69, $72, $3B)); + +//#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID \ +// {0x387477c2,0x69c7,0x11d2,0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} +// EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID : EFI_GUID = (Data1:$387477c2; +// Data2: $69C7; Data3: $11D2; Data4: ($8E, $39, $00, $A0, $C9, $69, $72, $3B)); + + // reversed +// EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID : EFI_GUID = (Data1:$c2777438; +// Data2: $C769; Data3: $D211; Data4: ($8E, $39, $00, $A0, $C9, $69, $72, $3B)); + +// EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID : EFI_GUID = +// (Data: ($c2, $77, $74, $38, $C7, $69, $D2, $11, $8E, $39, $00, $A0, $C9, $69, $72, $3B)); + +// Good definition ! + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID : EFI_GUID = + (Data: ( $38, $74, $77, $c2, $69, $C7, $11, $D2, $8E, $39, $00, $A0, $C9, $69, $72, $3B)); + const EFI_SUCCESS = 0; EFI_LOAD_ERROR = 1; @@ -79,9 +137,9 @@ const EFI_NOT_FOUND = 14; type - EFI_HANDLE = Cardinal; + EFI_HANDLE = NativeUInt; EFI_EVENT = pointer; - EFI_STATUS = Cardinal; + EFI_STATUS = NativeUInt; type EFI_INPUT_KEY = record @@ -92,8 +150,23 @@ type Type PCHAR16 = ^WideChar; PEFI_INPUT_KEY = ^EFI_INPUT_KEY; + // According to http://vzimmer.blogspot.fr/2015/08/efi-byte-code.html, + // their size should follow the pointer size. + // UINTN mean Unsigned natural integer + // INTN mean Signed natural integer + // TODO : 64 bits UINTN = Cardinal; PUINTN = ^UINTN; + + EFI_MEMORY_TYPE = (EfiReservedMemoryType,EfiLoaderCode,EfiLoaderData, + EfiBootServicesCode,EfiBootServicesData, + EfiRuntimeServicesCode,EfiRuntimeServicesData, + EfiConventionalMemory,EfiUnusableMemory, + EfiACPIReclaimMemory,EfiACPIMemoryNVS, + EfiMemoryMappedIO,EfiMemoryMappedIOPortSpace, + EfiPalCode,EfiMaxMemoryType); + +type P_SIMPLE_TEXT_OUTPUT_INTERFACE = ^_SIMPLE_TEXT_OUTPUT_INTERFACE; P_SIMPLE_INPUT_INTERFACE = ^_SIMPLE_INPUT_INTERFACE; @@ -202,14 +275,6 @@ Type {When returning to ConventialMemory always make it WB,SR,SW } {When getting the memory map, or on RT for runtime types } - EFI_MEMORY_TYPE = (EfiReservedMemoryType,EfiLoaderCode,EfiLoaderData, - EfiBootServicesCode,EfiBootServicesData, - EfiRuntimeServicesCode,EfiRuntimeServicesData, - EfiConventionalMemory,EfiUnusableMemory, - EfiACPIReclaimMemory,EfiACPIMemoryNVS, - EfiMemoryMappedIO,EfiMemoryMappedIOPortSpace, - EfiPalCode,EfiMaxMemoryType); - type EFI_PHYSICAL_ADDRESS = UINT64; @@ -233,15 +298,15 @@ Type EFI_INSTALL_PROTOCOL_INTERFACE = function ((* TODO *)):EFI_STATUS;cdecl; EFI_REINSTALL_PROTOCOL_INTERFACE = function ((* TODO *)):EFI_STATUS;cdecl; EFI_UNINSTALL_PROTOCOL_INTERFACE = function ((* TODO *)):EFI_STATUS;cdecl; - EFI_HANDLE_PROTOCOL = function ((* TODO *)):EFI_STATUS;cdecl; - EFI_REGISTER_PROTOCOL_NOTIFY = function ((* TODO *)):EFI_STATUS;cdecl; + EFI_HANDLE_PROTOCOL = function (Handle : EFI_HANDLE; var Protocol : EFI_GUID; var _Interface : pointer):EFI_STATUS;cdecl; + EFI_REGISTER_PROTOCOL_NOTIFY = function ((* TODOhand *)):EFI_STATUS;cdecl; EFI_LOCATE_HANDLE = function ((* TODO *)):EFI_STATUS;cdecl; EFI_LOCATE_DEVICE_PATH = function ((* TODO *)):EFI_STATUS;cdecl; EFI_INSTALL_CONFIGURATION_TABLE = function ((* TODO *)):EFI_STATUS;cdecl; EFI_IMAGE_LOAD = function ((* TODO *)):EFI_STATUS;cdecl; EFI_IMAGE_START = function ((* TODO *)):EFI_STATUS;cdecl; EFI_EXIT = function ((* TODO *)):EFI_STATUS;cdecl; - EFI_IMAGE_UNLOAD = function ((* TODO *)):EFI_STATUS;cdecl; + EFI_IMAGE_UNLOAD = function (ImageHandle : EFI_HANDLE):EFI_STATUS;cdecl; EFI_EXIT_BOOT_SERVICES = function ((* TODO *)):EFI_STATUS;cdecl; EFI_GET_NEXT_MONOTONIC_COUNT = function ((* TODO *)):EFI_STATUS;cdecl; EFI_STALL = function (Microseconds : UINT32):EFI_STATUS;cdecl; @@ -281,7 +346,7 @@ Type ReinstallProtocolInterface : EFI_REINSTALL_PROTOCOL_INTERFACE; UninstallProtocolInterface : EFI_UNINSTALL_PROTOCOL_INTERFACE; HandleProtocol : EFI_HANDLE_PROTOCOL; - PCHandleProtocol : EFI_HANDLE_PROTOCOL; + PCHandleProtocol : EFI_HANDLE_PROTOCOL; // Reserved acording to http://wiki.phoenix.com/wiki/index.php/EFI_BOOT_SERVICES RegisterProtocolNotify : EFI_REGISTER_PROTOCOL_NOTIFY; LocateHandle : EFI_LOCATE_HANDLE; LocateDevicePath : EFI_LOCATE_DEVICE_PATH; @@ -330,6 +395,66 @@ type EFI_SYSTEM_TABLE = _EFI_SYSTEM_TABLE; PEFI_SYSTEM_TABLE = ^EFI_SYSTEM_TABLE; + + const + EFI_IMAGE_INFORMATION_REVISION = $1000; + + { Source location of image } + { Images load options } + { Location of where image was loaded } + { If the driver image supports a dynamic unload request } + + {++ + + Copyright (c) 1998 Intel Corporation + + Module Name: + + devpath.h + + Abstract: + + Defines for parsing the EFI Device Path structures + + + + Revision History + + -- } + { } + { Device Path structures - Section C } + { } + + type + _EFI_DEVICE_PATH = record + _Type : UINT8; + SubType : UINT8; + Length : array[0..1] of UINT8; + end; + EFI_DEVICE_PATH = _EFI_DEVICE_PATH; + + type + EFI_LOADED_IMAGE = record + Revision : UINT32; + ParentHandle : EFI_HANDLE; + SystemTable : ^_EFI_SYSTEM_TABLE; + DeviceHandle : EFI_HANDLE; + FilePath : ^EFI_DEVICE_PATH; + Reserved : pointer; + LoadOptionsSize : UINT32; + LoadOptions : pointer; + ImageBase : pointer; + ImageSize : UINT64; + ImageCodeType : EFI_MEMORY_TYPE; + ImageDataType : EFI_MEMORY_TYPE; + Unload : EFI_IMAGE_UNLOAD; + end; + PEFI_LOADED_IMAGE = ^EFI_LOADED_IMAGE; + +{$IFDEF FPC} +{$PACKRECORDS DEFAULT} +{$ENDIF} + procedure Check(systemTable : EFI_SYSTEM_TABLE; status : EFI_STATUS); procedure Check(status : EFI_STATUS); @@ -351,6 +476,9 @@ procedure Init(systemTable : EFI_SYSTEM_TABLE); procedure PascalMain;stdcall;external name 'PASCALMAIN'; +procedure Debugger(s : WideString); +procedure Debugger(); + implementation { include system independent routines } @@ -377,9 +505,9 @@ end; procedure Check(systemTable : EFI_SYSTEM_TABLE; status : EFI_STATUS); var - msg : string; + msg : WideString; begin - msg := 'Error'; + msg := 'Default error'; case status of EFI_SUCCESS: @@ -443,13 +571,21 @@ begin end; else begin - // Error - msg := 'Error'; + if (status > MaxInt) and (status <= High(Cardinal)) then + begin + msg := 'Very high error number : suspicious...'; + end + else + begin + // Error + msg := 'Error not handled in Check'; + end; end; end; - WriteLn(''); - WriteLn(msg); + Debugger(''); + Debugger(msg); + Debugger('End of Check'); end; procedure Init(systemTable : EFI_SYSTEM_TABLE); @@ -462,15 +598,15 @@ begin SysTable := systemTable; { Setup heap } - myheapsize:=4096*100;// $ 20000; - myheaprealsize:=4096*100;// $ 20000; + myheapsize:=4096*1000;// $ 20000; + myheaprealsize:=4096*1000;// $ 20000; heapstart:=nil; heapstartpointer := nil; - heapstartpointer := SysOSAlloc(4096*100); + heapstartpointer := SysOSAlloc(4096*1000); if heapstartpointer <> nil then begin SysTable.ConOut^.OutputString(SysTable.ConOut, 'heapStartPointer initialization' + #13#10); - FillChar(heapstartpointer^, 4096*100, #0); + FillChar(heapstartpointer^, 4096*1000, #0); end else begin @@ -489,14 +625,36 @@ begin SysTable.ConOut^.OutputString(SysTable.ConOut, #13#10); end; +procedure Debugger(); +begin + {$ifdef UEFI} + SysTable.ConOut^.OutputString(SysTable.ConOut, PChar16('Debugger call : ' + #13#10)); + {$endif} +end; + +procedure Debugger(s : WideString); +begin + {$ifdef UEFI} + SysTable.ConOut^.OutputString(SysTable.ConOut, PChar16('Debugger call : ' + s + #13#10)); + {$endif} +end; + +var + s : WideString; + s1 : string; + function EFI_MAIN( imageHandle: EFI_HANDLE; systemTable : PEFI_SYSTEM_TABLE): EFI_STATUS; cdecl; [public, alias: 'EFI_MAIN']; +var + CurrentImage : EFI_LOADED_IMAGE; + pCurrentImage : PEFI_LOADED_IMAGE; + HandleProtocolResult : EFI_STATUS = 0; + myImageHandle : Cardinal; begin //try SysTable := systemTable^; SysTable.ConOut^.OutputString(SysTable.ConOut, 'EFI_MAIN start' + #13#10); - StackLength := CheckInitialStkLen ($1000000); StackBottom := StackTop - StackLength; @@ -507,15 +665,20 @@ begin heapstartpointer := nil; heapstartpointer := SysOSAlloc(4096*100); FillChar(heapstartpointer^, myheaprealsize, #0); + + SysTable.ConOut^.OutputString(SysTable.ConOut, 'just before InitHeap' + #13#10); + InitHeap; + SysTable.ConOut^.OutputString(SysTable.ConOut, 'just after InitHeap' + #13#10); + DefaultSystemCodePage := CP_UTF16; DefaultRTLFileSystemCodePage := CP_UTF16; DefaultFileSystemCodePage := CP_UTF16; SetMultiByteConversionCodePage(CP_UTF16); - WriteLn('start'); - + Debugger('start'); + if heapstartpointer <> nil then begin SysTable.ConOut^.OutputString(SysTable.ConOut, 'heapStartPointer initialization' + #13#10); @@ -531,9 +694,58 @@ begin SysInitStdIO; { Reset IO Error } InOutRes:=0; + Debugger('before InitSystemThreads'); + InitSystemThreads; SysTable.ConOut^.OutputString(SysTable.ConOut, #13#10); + myImageHandle := imageHandle; + Debugger('After afectation'); + s1 := HexStr(myImageHandle, 8) + #13#10 + #0#0; + Debugger('After HexStr 1'); + + Debugger(s1); + + pCurrentImage := @CurrentImage; + HandleProtocolResult := + SysTable.BootServices^.HandleProtocol(imageHandle, LOADED_IMAGE_PROTOCOL, + //SysTable.BootServices^.HandleProtocol(imageHandle, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID, + pCurrentImage); + if pCurrentImage = nil then + begin + Debugger('pCurrentImage == nil'); + end + else + begin + Debugger('pCurrentImage <> nil'); + end; + if pCurrentImage^.Revision = EFI_IMAGE_INFORMATION_REVISION then + begin + Debugger('Revision OK'); + // Print loaded address + Debugger('Loaded address : '); + Debugger(HexStr(PEFI_LOADED_IMAGE(pCurrentImage^.ImageBase))); + Debugger('Size : '); + Debugger(HexStr(PEFI_LOADED_IMAGE(pCurrentImage^.ImageSize))); + end + else + Debugger('Bas revision number'); + begin + + end; + Check(HandleProtocolResult); + s := HexStr(HandleProtocolResult, 8); + Debugger('After HexStr 2'); + Debugger(s); + if HandleProtocolResult = EFI_SUCCESS then + begin + Debugger('Success in HandleProtocol'); + end + else + begin + Debugger('Error in HandleProtocol'); + end; + PascalMain; WriteLn('End of EFI_MAIN...'); //except |