我想 Boot 到我的NASM内核。但它是黑屏,并给出错误虚拟机无法在VMWare中引导。没有打印。代码:
内核.asm
; generate 64-bit code
bits 64
; use relative addresses
default rel
; contains the code that will run
section .text
; allows the linker to see the entry symbol
global start
%include "kernel-functions.asm"
%include "kernel-efi.asm"
%include "kernel-api.asm"
start:
; save the location of UEFI
mov [ptrUEFI], rsp
; reserve space for 4 arguments
sub rsp, 4 * 8
; see http://www.uefi.org/sites/default/files/resources/UEFI Spec 2_7_A Sept 6.pdf#G6.1000024
; the "2.3.4.1 Handoff State" section
; rcx is the 1st argument passed to us by the UEFI firmware
; it will contain the EFI_HANDLE
mov [hndImageHandle], rcx
; rdx is the 2nd argument passed to us by the UEFI firmware
; it points to the EFI_SYSTEM_TABLE
mov [ptrSystemTable], rdx
; verify the EFI_TABLE_HEADER.Signature
call apiVerifySignature
; output the OS and Firmware versions
call apiOutputHeader
; locate a graphics device and allocate a frame buffer
call apiGetFrameBuffer
; get a memory map and exit UEFI boot services
call apiExitUEFI
; load our kernel
call apiLoadKernel
add rsp, 4 * 8
mov rax, EFI_SUCCESS
ret
error:
; move to the location of UEFI and return
mov rsp, [ptrUEFI]
ret
errorCode:
; save our error code
push rax
; display the message
mov rcx, strErrorCode
call efiOutputString
; grab our error code and write it
; see the UEFI definitions in kernel-efi.asm
mov rcx, [rsp]
call funIntegerToAscii
; restore the error code
pop rax
jmp error
codesize equ $ - $$
; contains nothing - but it is required by UEFI
section .reloc
section .multiboot_header
; contains the data being stored
section .data
; UEFI requires we use Unicode strings
strHeader db __utf16__ `Rootupapps OS v0.1\r\nRunning on \0`
strHeaderV db __utf16__ ` v\0`
strErrorCode db __utf16__ `\r\n\nError Code #\0`
strDebugText db __utf16__ `\r\n\nDebug: \0`
; stores the location of UEFI
ptrUEFI dq 0
; stores the EFI_HANDLE
hndImageHandle dq 0
; stores the EFI_SYSTEM_TABLE
ptrSystemTable dq 0
; stores the EFI_GRAPHICS_OUTPUT_PROTOCOL
ptrInterface dq 0
; stores the memory map data
intMemoryMapSize dq EFI_MEMORY_DESCRIPTOR_size * 1024
bufMemoryMap resb EFI_MEMORY_DESCRIPTOR_size * 1024
ptrMemoryMapKey dq 0
ptrMemoryMapDescSize dq 0
ptrMemoryMapDescVersion dq 0
; stores the frame buffer base
ptrFrameBuffer dq 0
datasize equ $ - $$
内核-api.asm
apiVerifySignature:
; get the signature for the loaded EFI_SYSTEM_TABLE
mov rcx, [ptrSystemTable]
mov rcx, [rcx + EFI_SYSTEM_TABLE.Hdr + EFI_TABLE_HEADER.Signature]
; get the signature defined in the UEFI spec
; see http://www.uefi.org/sites/default/files/resources/UEFI Spec 2_7_A Sept 6.pdf#G8.1001773
mov rdx, EFI_SYSTEM_TABLE_SIGNATURE
; set our error code
mov rax, EFI_LOAD_ERROR
; compare the signatures and return the error code when they don't match
cmp rdx, rcx
jne error
mov rax, EFI_SUCCESS
ret
apiOutputHeader:
; clear the screen
call efiClearScreen
; write the header
mov rcx, strHeader
call efiOutputString
; write the firmware vendor
mov rcx, [ptrSystemTable]
mov rcx, [rcx + EFI_SYSTEM_TABLE.FirmwareVendor]
call efiOutputString
; write the v
mov rcx, strHeaderV
call efiOutputString
; write the firmware revision
mov rcx, [ptrSystemTable]
mov rcx, [rcx + EFI_SYSTEM_TABLE.FirmwareRevision]
call funIntegerToAscii
ret
apiGetFrameBuffer:
; locate the first EFI_GRAPHICS_OUTPUT_PROTOCOL
; and allocate a frame buffer
call efiLocateProtocol
; get the base address of the frame buffer
mov rcx, [ptrInterface]
mov rcx, [rcx + EFI_GRAPHICS_OUTPUT_PROTOCOL.Mode]
mov rcx, [rcx + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.FrameBufferBase]
mov [ptrFrameBuffer], rcx
ret
apiExitUEFI:
call efiGetMemoryMap
call efiExitBootServices
ret
apiLoadKernel:
; verify we have reached this point
; by resetting the machine
; mov rax, [ptrSystemTable]
; mov rax, [rax + EFI_SYSTEM_TABLE.RuntimeServices]
; call [rax + EFI_RUNTIME_SERVICES.ResetSystem]
; set the 1st argument to our frame buffer
mov rcx, [ptrFrameBuffer]
; set the 2nd argument to our start position
mov rdx, 0
; set the 3rd argument to our end position
; this should be in multiples of 4
mov r8, 1024 * 100
call funDrawLine
ret
内核定义.asm
EFI_SUCCESS equ 0
EFI_LOAD_ERROR equ 0x8000000000000001 ; 9223372036854775809
EFI_INVALID_PARAMETER equ 0x8000000000000002 ; 9223372036854775810
EFI_UNSUPPORTED equ 0x8000000000000003 ; 9223372036854775811
EFI_BAD_BUFFER_SIZE equ 0x8000000000000004 ; 9223372036854775812
EFI_BUFFER_TOO_SMALL equ 0x8000000000000005 ; 9223372036854775813
EFI_NOT_READY equ 0x8000000000000006 ; 9223372036854775814
EFI_NOT_FOUND equ 0x8000000000000014 ; 9223372036854775828
EFI_SYSTEM_TABLE_SIGNATURE equ 0x5453595320494249
EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID db 0xde, 0xa9, 0x42, 0x90, 0xdc, 0x23, 0x38, 0x4a
db 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a
%macro UINTN 0
RESQ 1
alignb 8
%endmacro
%macro UINT32 0
RESD 1
alignb 4
%endmacro
%macro UINT64 0
RESQ 1
alignb 8
%endmacro
%macro EFI_HANDLE 0
RESQ 1
alignb 8
%endmacro
%macro POINTER 0
RESQ 1
alignb 8
%endmacro
struc EFI_TABLE_HEADER
.Signature UINT64
.Revision UINT32
.HeaderSize UINT32
.CRC32 UINT32
.Reserved UINT32
endstruc
struc EFI_SYSTEM_TABLE
.Hdr RESB EFI_TABLE_HEADER_size
.FirmwareVendor POINTER
.FirmwareRevision UINT32
.ConsoleInHandle EFI_HANDLE
.ConIn POINTER
.ConsoleOutHandle EFI_HANDLE
.ConOut POINTER
.StandardErrorHandle EFI_HANDLE
.StdErr POINTER
.RuntimeServices POINTER
.BootServices POINTER
.NumberOfTableEntries UINTN
.ConfigurationTable POINTER
endstruc
struc EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
.Reset POINTER
.OutputString POINTER
.TestString POINTER
.QueryMode POINTER
.SetMode POINTER
.SetAttribute POINTER
.ClearScreen POINTER
.SetCursorPosition POINTER
.EnableCursor POINTER
.Mode POINTER
endstruc
struc EFI_BOOT_SERVICES
.Hdr RESB EFI_TABLE_HEADER_size
.RaiseTPL POINTER
.RestoreTPL POINTER
.AllocatePages POINTER
.FreePages POINTER
.GetMemoryMap POINTER
.AllocatePool POINTER
.FreePool POINTER
.CreateEvent POINTER
.SetTimer POINTER
.WaitForEvent POINTER
.SignalEvent POINTER
.CloseEvent POINTER
.CheckEvent POINTER
.InstallProtocolInterface POINTER
.ReinstallProtocolInterface POINTER
.UninstallProtocolInterface POINTER
.HandleProtocol POINTER
.Reserved POINTER
.RegisterProtocolNotify POINTER
.LocateHandle POINTER
.LocateDevicePath POINTER
.InstallConfigurationTable POINTER
.LoadImage POINTER
.StartImage POINTER
.Exit POINTER
.UnloadImage POINTER
.ExitBootServices POINTER
.GetNextMonotonicCount POINTER
.Stall POINTER
.SetWatchdogTimer POINTER
.ConnectController POINTER
.DisconnectController POINTER
.OpenProtocol POINTER
.CloseProtocol POINTER
.OpenProtocolInformation POINTER
.ProtocolsPerHandle POINTER
.LocateHandleBuffer POINTER
.LocateProtocol POINTER
.InstallMultipleProtocolInterfaces POINTER
.UninstallMultipleProtocolInterfaces POINTER
.CalculateCrc32 POINTER
.CopyMem POINTER
.SetMem POINTER
.CreateEventEx POINTER
endstruc
struc EFI_RUNTIME_SERVICES
.Hdr RESB EFI_TABLE_HEADER_size
.GetTime POINTER
.SetTime POINTER
.GetWakeupTime POINTER
.SetWakeupTime POINTER
.SetVirtualAddressMap POINTER
.ConvertPointer POINTER
.GetVariable POINTER
.GetNextVariableName POINTER
.SetVariable POINTER
.GetNextHighMonotonicCount POINTER
.ResetSystem POINTER
.UpdateCapsule POINTER
.QueryCapsuleCapabilities POINTER
.QueryVariableInfo POINTER
endstruc
struc EFI_GRAPHICS_OUTPUT_PROTOCOL
.QueryMode POINTER
.SetMode POINTER
.Blt POINTER
.Mode POINTER
endstruc
; see Errata A page 494
struc EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
.MaxMode UINT32
.Mode UINT32
.Info POINTER
.SizeOfInfo UINTN
.FrameBufferBase UINT64
.FrameBufferSize UINTN
endstruc
; the Related Definitions section
struc EFI_MEMORY_DESCRIPTOR
.Type UINT32
.PhysicalStart POINTER
.VirtualStart POINTER
.NumberOfPages UINT64
.Attribute UINT64
endstruc
; ---- Function Wrappers for the Protocols / Services
efiOutputString:
; set the 2nd argument to the passed in string
mov rdx, rcx
; get the EFI_SYSTEM_TABLE
mov rcx, [ptrSystemTable]
; set the 1st argument to EFI_SYSTEM_TABLE.ConOut
; which is pointing to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
mov rcx, [rcx + EFI_SYSTEM_TABLE.ConOut]
; run EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString
call [rcx + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString]
; display any errors
cmp rax, EFI_SUCCESS
jne errorCode
ret
efiClearScreen:
; get the EFI_SYSTEM_TABLE
mov rcx, [ptrSystemTable]
; set the 1st argument to EFI_SYSTEM_TABLE.ConOut
; which is pointing to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
mov rcx, [rcx + EFI_SYSTEM_TABLE.ConOut]
; run EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen
call [rcx + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen]
; display any errors
cmp rax, EFI_SUCCESS
jne errorCode
ret
efiLocateProtocol:
; get the EFI_SYSTEM_TABLE
mov rax, [ptrSystemTable]
; get the EFI_SYSTEM_TABLE.BootServices
; which is pointing to EFI_BOOT_SERVICES
mov rax, [rax + EFI_SYSTEM_TABLE.BootServices]
; set the 1st argument to the GUID for the graphics protocol
mov rcx, EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID
; set the 2nd argument to NULL
mov rdx, 0
; set the 3rd argument to a variable that holds
; the returned EFI_GRAPHICS_OUTPUT_PROTOCOL
lea r8, [ptrInterface]
; run EFI_BOOT_SERVICES.LocateProtocol
call [rax + EFI_BOOT_SERVICES.LocateProtocol]
; display any errors
cmp rax, EFI_SUCCESS
jne errorCode
ret
efiGetMemoryMap:
; get the EFI_SYSTEM_TABLE
mov rax, [ptrSystemTable]
; get the EFI_SYSTEM_TABLE.BootServices
; which is pointing to EFI_BOOT_SERVICES
mov rax, [rax + EFI_SYSTEM_TABLE.BootServices]
; set the 1st argument to the memory map buffer size
lea rcx, [intMemoryMapSize]
; set the 2nd argument to the memory map buffer
lea rdx, [bufMemoryMap]
; set the 3rd argument to a variable that holds
; the returned memory map key
lea r8, [ptrMemoryMapKey]
; set the 4th argument to a variable that holds
; the returned EFI_MEMORY_DESCRIPTOR size
lea r9, [ptrMemoryMapDescSize]
; set the 5th argument to a variable that holds
; the returned EFI_MEMORY_DESCRIPTOR version
lea r10, [ptrMemoryMapDescVersion]
; save the top of the stack so we can return here
mov rbx, rsp
; save the 5th argument to the stack
push r10
; run EFI_BOOT_SERVICES.GetMemoryMap
call [rax + EFI_BOOT_SERVICES.GetMemoryMap]
; display any errors
cmp rax, EFI_SUCCESS
jne errorCode
; return to the previous stack location
mov rsp, rbx
ret
efiExitBootServices:
; get the EFI_SYSTEM_TABLE
mov rax, [ptrSystemTable]
; get the EFI_SYSTEM_TABLE.BootServices
; which is pointing to EFI_BOOT_SERVICES
mov rax, [rax + EFI_SYSTEM_TABLE.BootServices]
; set the 1st argument to the stored EFI_HANDLE
mov rcx, [hndImageHandle]
; set the 2nd argument to the memory map key
mov rdx, [ptrMemoryMapKey]
; run EFI_BOOT_SERVICES.ExitBootServices
call [rax + EFI_BOOT_SERVICES.ExitBootServices]
; display any errors
cmp rax, EFI_SUCCESS
jne errorCode
ret
内核函数.asm
funIntegerToAscii:
; save rbx and rsi so that we can restore them later
push rbx
push rsi
; set rax to the passed in integer
mov rax, rcx
; set our counter to 0
mov rbx, 0
; there is no return and so we continue
funIntegerToAsciiDivide:
; increment our counter by 1
inc rbx
; reset our ascii character
mov rdx, 0
; divide rax by 10
; idiv works on rax
; e.g. 123 / 10 = 12.3
mov rsi, 10
idiv rsi
; the remainder is stored in rdx
; add 48 to get it's ASCII value
; 3 + 48 = 51 (the character '3')
add rdx, 48
; save the ASCII value to the stack
push rdx
; can rax be divided again
; rax = 12, yes it can
cmp rax, 0
jnz funIntegerToAsciiDivide
; there is no return and so we continue
funIntegerToAsciiOutput:
; increment our counter by 1
dec rbx
; set the 1st argument to the top of the stack
; 1 <- we are here
; 2
; 3
mov rcx, rsp
; write the ASCII character there and then remove it
call efiOutputString
pop rax
; have we written all the characters
cmp rbx, 0
jnz funIntegerToAsciiOutput
; restore rbx and rsi
pop rsi
pop rbx
ret
funLoopForever:
jmp funLoopForever
funDrawLine:
; draw a single pixel
mov [rcx + rdx], byte 0x00 ; blue
mov [rcx + rdx + 1], byte 0x00 ; green
mov [rcx + rdx + 2], byte 0xFF ; red
mov [rcx + rdx + 3], byte 0xFF ; alpha
; skip to the next pixel
add rdx, 4
; stop drawing when we've reached rdx
cmp rdx, r8
jne funDrawLine
ret
但我无法 Boot UEFI操作系统。我的错误在哪里?请帮助我给予缺失代码或删除错误提供商代码。
1条答案
按热度按时间7jmck4yq1#
看起来您加载了正确的寄存器,但没有在堆栈上创建影子空间。在AMD64中,调用约定与Windows中使用的约定类似。在调用函数之前,创建影子空间并对齐堆栈是很重要的。
下面是一些例子,如果你想比较一下的话:https://github.com/bitRAKE/UEFI_playground