mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-16 02:33:28 +00:00
add device/uefi and device/amd64
This commit is contained in:
@@ -0,0 +1,74 @@
|
|||||||
|
//go:build amd64
|
||||||
|
|
||||||
|
package amd64
|
||||||
|
|
||||||
|
const (
|
||||||
|
CPUIDTimeStampCounter = 0x15
|
||||||
|
CPUIDProcessorFrequency = 0x16
|
||||||
|
)
|
||||||
|
|
||||||
|
type CPUExtendedFamily uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
CPUFamilyIntelCore CPUExtendedFamily = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
//export asmPause
|
||||||
|
func AsmPause()
|
||||||
|
|
||||||
|
//export asmReadRdtsc
|
||||||
|
func AsmReadRdtsc() uint64
|
||||||
|
|
||||||
|
//export asmCpuid
|
||||||
|
func AsmCpuid(index uint32, registerEax *uint32, registerEbx *uint32, registerEcx *uint32) int
|
||||||
|
|
||||||
|
var maxCpuidIndex uint32
|
||||||
|
var stdVendorName0 uint32
|
||||||
|
var stdCpuid1Eax uint32
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
AsmCpuid(0, &maxCpuidIndex, &stdVendorName0, nil)
|
||||||
|
AsmCpuid(1, &stdCpuid1Eax, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getExtendedCPUFamily() CPUExtendedFamily {
|
||||||
|
family := CPUExtendedFamily((stdCpuid1Eax >> 8) & 0x0f)
|
||||||
|
family += CPUExtendedFamily((stdCpuid1Eax >> 20) & 0xff)
|
||||||
|
return family
|
||||||
|
}
|
||||||
|
|
||||||
|
func isIntel() bool {
|
||||||
|
return stdVendorName0 == 0x756e6547
|
||||||
|
}
|
||||||
|
|
||||||
|
func isIntelFamilyCore() bool {
|
||||||
|
return isIntel() && getExtendedCPUFamily() == CPUFamilyIntelCore
|
||||||
|
}
|
||||||
|
|
||||||
|
func InternalGetPerformanceCounterFrequency() uint64 {
|
||||||
|
if maxCpuidIndex >= CPUIDTimeStampCounter {
|
||||||
|
return cpuidCoreClockCalculateTSCFrequency()
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func cpuidCoreClockCalculateTSCFrequency() uint64 {
|
||||||
|
var eax uint32
|
||||||
|
var ebx uint32
|
||||||
|
var ecx uint32
|
||||||
|
|
||||||
|
AsmCpuid(CPUIDTimeStampCounter, &eax, &ebx, &ecx)
|
||||||
|
if eax == 0 || ebx == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
coreCrystalFrequency := uint64(ecx)
|
||||||
|
if coreCrystalFrequency == 0 {
|
||||||
|
if !isIntelFamilyCore() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
coreCrystalFrequency = 24000000
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((coreCrystalFrequency * uint64(ebx)) + (uint64(eax) / 2)) / uint64(eax)
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
.section .text
|
||||||
|
|
||||||
|
.global asmPause
|
||||||
|
asmPause:
|
||||||
|
pause
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global asmReadRdtsc
|
||||||
|
asmReadRdtsc:
|
||||||
|
rdtsc
|
||||||
|
shlq $0x20, %rdx
|
||||||
|
orq %rdx, %rax
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global asmCpuid
|
||||||
|
asmCpuid:
|
||||||
|
pushq %rbx
|
||||||
|
|
||||||
|
mov %ecx, %eax
|
||||||
|
pushq %rax
|
||||||
|
|
||||||
|
pushq %rdx
|
||||||
|
cpuid
|
||||||
|
|
||||||
|
test %r9, %r9
|
||||||
|
jz .SkipEcx
|
||||||
|
mov %ecx, (%r9)
|
||||||
|
.SkipEcx:
|
||||||
|
popq %rcx
|
||||||
|
jrcxz .SkipEax
|
||||||
|
mov %eax, (%rcx)
|
||||||
|
.SkipEax:
|
||||||
|
mov %r8, %rcx
|
||||||
|
jrcxz .SkipEbx
|
||||||
|
mov %ebx, (%rcx)
|
||||||
|
.SkipEbx:
|
||||||
|
popq %rax
|
||||||
|
popq %rbx
|
||||||
|
ret
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
//go:build i386 || amd64
|
||||||
|
|
||||||
|
package uefi
|
||||||
|
|
||||||
|
import "device/amd64"
|
||||||
|
|
||||||
|
func Ticks() uint64 {
|
||||||
|
return amd64.AsmReadRdtsc()
|
||||||
|
}
|
||||||
|
|
||||||
|
func CpuPause() {
|
||||||
|
amd64.AsmPause()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTSCFrequency() uint64 {
|
||||||
|
return amd64.InternalGetPerformanceCounterFrequency()
|
||||||
|
}
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
.section .text
|
||||||
|
|
||||||
|
.global uefiCall0
|
||||||
|
uefiCall0:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $0x20, %rsp
|
||||||
|
callq *%rcx
|
||||||
|
movq %rbp, %rsp
|
||||||
|
popq %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global uefiCall1
|
||||||
|
uefiCall1:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $0x20, %rsp
|
||||||
|
movq %rcx, %rax
|
||||||
|
movq %rdx, %rcx
|
||||||
|
callq *%rax
|
||||||
|
movq %rbp, %rsp
|
||||||
|
popq %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global uefiCall2
|
||||||
|
uefiCall2:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $0x20, %rsp
|
||||||
|
movq %rcx, %rax
|
||||||
|
movq %rdx, %rcx
|
||||||
|
movq %r8, %rdx
|
||||||
|
callq *%rax
|
||||||
|
movq %rbp, %rsp
|
||||||
|
popq %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global uefiCall3
|
||||||
|
uefiCall3:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $0x20, %rsp
|
||||||
|
movq %rcx, %rax
|
||||||
|
movq %rdx, %rcx
|
||||||
|
movq %r8, %rdx
|
||||||
|
movq %r9, %r8
|
||||||
|
callq *%rax
|
||||||
|
movq %rbp, %rsp
|
||||||
|
popq %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global uefiCall4
|
||||||
|
uefiCall4:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $0x20, %rsp
|
||||||
|
movq %rcx, %rax
|
||||||
|
movq %rdx, %rcx
|
||||||
|
movq %r8, %rdx
|
||||||
|
movq %r9, %r8
|
||||||
|
movq 0x30(%rbp), %r9
|
||||||
|
callq *%rax
|
||||||
|
movq %rbp, %rsp
|
||||||
|
popq %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global uefiCall5
|
||||||
|
uefiCall5:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $0x30, %rsp
|
||||||
|
movq %rcx, %rax
|
||||||
|
movq %rdx, %rcx
|
||||||
|
movq %r8, %rdx
|
||||||
|
movq %r9, %r8
|
||||||
|
movq 0x30(%rbp), %r9
|
||||||
|
movq 0x38(%rbp), %r10
|
||||||
|
movq %r10, 0x20(%rsp)
|
||||||
|
callq *%rax
|
||||||
|
movq %rbp, %rsp
|
||||||
|
popq %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global uefiCall6
|
||||||
|
uefiCall6:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $0x30, %rsp
|
||||||
|
movq %rcx, %rax
|
||||||
|
movq %rdx, %rcx
|
||||||
|
movq %r8, %rdx
|
||||||
|
movq %r9, %r8
|
||||||
|
movq 0x30(%rbp), %r9
|
||||||
|
movq 0x38(%rbp), %r10
|
||||||
|
movq %r10, 0x20(%rsp)
|
||||||
|
movq 0x40(%rbp), %r10
|
||||||
|
movq %r10, 0x28(%rsp)
|
||||||
|
callq *%rax
|
||||||
|
movq %rbp, %rsp
|
||||||
|
popq %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global uefiCall7
|
||||||
|
uefiCall7:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $0x40, %rsp
|
||||||
|
movq %rcx, %rax
|
||||||
|
movq %rdx, %rcx
|
||||||
|
movq %r8, %rdx
|
||||||
|
movq %r9, %r8
|
||||||
|
movq 0x30(%rbp), %r9
|
||||||
|
movq 0x38(%rbp), %r10
|
||||||
|
movq %r10, 0x20(%rsp)
|
||||||
|
movq 0x40(%rbp), %r10
|
||||||
|
movq %r10, 0x28(%rsp)
|
||||||
|
movq 0x48(%rbp), %r10
|
||||||
|
movq %r10, 0x30(%rsp)
|
||||||
|
callq *%rax
|
||||||
|
movq %rbp, %rsp
|
||||||
|
popq %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global uefiCall8
|
||||||
|
uefiCall8:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $0x40, %rsp
|
||||||
|
movq %rcx, %rax
|
||||||
|
movq %rdx, %rcx
|
||||||
|
movq %r8, %rdx
|
||||||
|
movq %r9, %r8
|
||||||
|
movq 0x30(%rbp), %r9
|
||||||
|
movq 0x38(%rbp), %r10
|
||||||
|
movq %r10, 0x20(%rsp)
|
||||||
|
movq 0x40(%rbp), %r10
|
||||||
|
movq %r10, 0x28(%rsp)
|
||||||
|
movq 0x48(%rbp), %r10
|
||||||
|
movq %r10, 0x30(%rsp)
|
||||||
|
movq 0x50(%rbp), %r10
|
||||||
|
movq %r10, 0x38(%rsp)
|
||||||
|
callq *%rax
|
||||||
|
movq %rbp, %rsp
|
||||||
|
popq %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global uefiCall9
|
||||||
|
uefiCall9:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $0x50, %rsp
|
||||||
|
movq %rcx, %rax
|
||||||
|
movq %rdx, %rcx
|
||||||
|
movq %r8, %rdx
|
||||||
|
movq %r9, %r8
|
||||||
|
movq 0x30(%rbp), %r9
|
||||||
|
movq 0x38(%rbp), %r10
|
||||||
|
movq %r10, 0x20(%rsp)
|
||||||
|
movq 0x40(%rbp), %r10
|
||||||
|
movq %r10, 0x28(%rsp)
|
||||||
|
movq 0x48(%rbp), %r10
|
||||||
|
movq %r10, 0x30(%rsp)
|
||||||
|
movq 0x50(%rbp), %r10
|
||||||
|
movq %r10, 0x38(%rsp)
|
||||||
|
movq 0x58(%rbp), %r10
|
||||||
|
movq %r10, 0x40(%rsp)
|
||||||
|
callq *%rax
|
||||||
|
movq %rbp, %rsp
|
||||||
|
popq %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global uefiCall10
|
||||||
|
uefiCall10:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $0x50, %rsp
|
||||||
|
movq %rcx, %rax
|
||||||
|
movq %rdx, %rcx
|
||||||
|
movq %r8, %rdx
|
||||||
|
movq %r9, %r8
|
||||||
|
movq 0x30(%rbp), %r9
|
||||||
|
movq 0x38(%rbp), %r10
|
||||||
|
movq %r10, 0x20(%rsp)
|
||||||
|
movq 0x40(%rbp), %r10
|
||||||
|
movq %r10, 0x28(%rsp)
|
||||||
|
movq 0x48(%rbp), %r10
|
||||||
|
movq %r10, 0x30(%rsp)
|
||||||
|
movq 0x50(%rbp), %r10
|
||||||
|
movq %r10, 0x38(%rsp)
|
||||||
|
movq 0x58(%rbp), %r10
|
||||||
|
movq %r10, 0x40(%rsp)
|
||||||
|
movq 0x60(%rbp), %r10
|
||||||
|
movq %r10, 0x48(%rsp)
|
||||||
|
callq *%rax
|
||||||
|
movq %rbp, %rsp
|
||||||
|
popq %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global ___chkstk_ms
|
||||||
|
___chkstk_ms:
|
||||||
|
ret
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package uefi
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//export uefiCall0
|
||||||
|
func UefiCall0(fn uintptr) EFI_STATUS
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:export uefiCall1
|
||||||
|
func UefiCall1(fn uintptr, a uintptr) EFI_STATUS
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:export uefiCall2
|
||||||
|
func UefiCall2(fn uintptr, a uintptr, b uintptr) EFI_STATUS
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:export uefiCall3
|
||||||
|
func UefiCall3(fn uintptr, a uintptr, b uintptr, c uintptr) EFI_STATUS
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:export uefiCall4
|
||||||
|
func UefiCall4(fn uintptr, a uintptr, b uintptr, c uintptr, d uintptr) EFI_STATUS
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:export uefiCall5
|
||||||
|
func UefiCall5(fn uintptr, a uintptr, b uintptr, c uintptr, d uintptr, e uintptr) EFI_STATUS
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:export uefiCall6
|
||||||
|
func UefiCall6(fn uintptr, a uintptr, b uintptr, c uintptr, d uintptr, e uintptr, f uintptr) EFI_STATUS
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:export uefiCall7
|
||||||
|
func UefiCall7(fn uintptr, a uintptr, b uintptr, c uintptr, d uintptr, e uintptr, f uintptr, g uintptr) EFI_STATUS
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:export uefiCall8
|
||||||
|
func UefiCall8(fn uintptr, a uintptr, b uintptr, c uintptr, d uintptr, e uintptr, f uintptr, g uintptr, h uintptr) EFI_STATUS
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:export uefiCall9
|
||||||
|
func UefiCall9(fn uintptr, a uintptr, b uintptr, c uintptr, d uintptr, e uintptr, f uintptr, g uintptr, h uintptr, i uintptr) EFI_STATUS
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
//go:export uefiCall10
|
||||||
|
func UefiCall10(fn uintptr, a uintptr, b uintptr, c uintptr, d uintptr, e uintptr, f uintptr, g uintptr, h uintptr, i uintptr, j uintptr) EFI_STATUS
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package uefi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unicode/utf16"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StringToCHAR16 converts a Go string to a UTF-16 code unit slice.
|
||||||
|
func StringToCHAR16(s string) []CHAR16 {
|
||||||
|
if s == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
encoded := utf16.Encode([]rune(s))
|
||||||
|
out := make([]CHAR16, len(encoded))
|
||||||
|
for i, r := range encoded {
|
||||||
|
out[i] = CHAR16(r)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToCHAR16Z converts a Go string to a NUL-terminated UTF-16 code unit slice.
|
||||||
|
func StringToCHAR16Z(s string) []CHAR16 {
|
||||||
|
out := StringToCHAR16(s)
|
||||||
|
return append(out, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesToCHAR16 converts UTF-8 text bytes to a UTF-16 code unit slice.
|
||||||
|
func BytesToCHAR16(b []byte) []CHAR16 {
|
||||||
|
return StringToCHAR16(string(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesToCHAR16Z converts UTF-8 text bytes to a NUL-terminated UTF-16 code unit slice.
|
||||||
|
func BytesToCHAR16Z(b []byte) []CHAR16 {
|
||||||
|
return StringToCHAR16Z(string(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHAR16ToString converts a UTF-16 code unit slice to a Go string.
|
||||||
|
func CHAR16ToString(input []CHAR16) string {
|
||||||
|
if len(input) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
units := make([]uint16, len(input))
|
||||||
|
for i, c := range input {
|
||||||
|
units[i] = uint16(c)
|
||||||
|
}
|
||||||
|
return string(utf16.Decode(units))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHAR16ToBytes converts a UTF-16 code unit slice to UTF-8 text bytes.
|
||||||
|
func CHAR16ToBytes(input []CHAR16) []byte {
|
||||||
|
return []byte(CHAR16ToString(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHAR16PtrToString converts a NUL-terminated UTF-16 string pointer to a Go string.
|
||||||
|
func CHAR16PtrToString(input *CHAR16) string {
|
||||||
|
if input == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr := uintptr(unsafe.Pointer(input))
|
||||||
|
length := 0
|
||||||
|
for *(*CHAR16)(unsafe.Pointer(ptr)) != 0 {
|
||||||
|
length++
|
||||||
|
ptr += 2
|
||||||
|
}
|
||||||
|
return CHAR16PtrLenToString(input, length)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHAR16PtrLenToString converts a UTF-16 string pointer with a known code unit count to a Go string.
|
||||||
|
func CHAR16PtrLenToString(input *CHAR16, length int) string {
|
||||||
|
if input == nil || length <= 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return CHAR16ToString(unsafe.Slice(input, length))
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
//go:build uefi
|
||||||
|
|
||||||
|
package uefi
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
var calibrateMutex sync.Mutex
|
||||||
|
var calculatedFrequency uint64
|
||||||
|
|
||||||
|
func TicksFrequency() uint64 {
|
||||||
|
frequency := getTSCFrequency()
|
||||||
|
if frequency > 0 {
|
||||||
|
return frequency
|
||||||
|
}
|
||||||
|
|
||||||
|
calibrateMutex.Lock()
|
||||||
|
defer calibrateMutex.Unlock()
|
||||||
|
if calculatedFrequency > 0 {
|
||||||
|
return calculatedFrequency
|
||||||
|
}
|
||||||
|
|
||||||
|
var event EFI_EVENT
|
||||||
|
var index UINTN
|
||||||
|
if BS().CreateEvent(EVT_TIMER, TPL_CALLBACK, nil, nil, &event) != EFI_SUCCESS {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
defer BS().CloseEvent(event)
|
||||||
|
|
||||||
|
start := Ticks()
|
||||||
|
if BS().SetTimer(event, TimerPeriodic, 250*10000) != EFI_SUCCESS {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if BS().WaitForEvent(1, &event, &index) != EFI_SUCCESS {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
calculatedFrequency = (Ticks() - start) * 4
|
||||||
|
return calculatedFrequency
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package uefi
|
||||||
|
|
||||||
|
type UINTN uintptr
|
||||||
|
type EFI_STATUS UINTN
|
||||||
|
type EFI_TPL UINTN
|
||||||
|
type EFI_HANDLE uintptr
|
||||||
|
type EFI_EVENT uintptr
|
||||||
|
type EFI_PHYSICAL_ADDRESS uint64
|
||||||
|
|
||||||
|
type CHAR16 uint16
|
||||||
|
type BOOLEAN bool
|
||||||
|
type VOID byte
|
||||||
|
|
||||||
|
type EFI_GUID struct {
|
||||||
|
Data1 uint32
|
||||||
|
Data2 uint16
|
||||||
|
Data3 uint16
|
||||||
|
Data4 [8]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type EFI_TABLE_HEADER struct {
|
||||||
|
Signature uint64
|
||||||
|
Revision uint32
|
||||||
|
HeaderSize uint32
|
||||||
|
CRC32 uint32
|
||||||
|
Reserved uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type EFI_ALLOCATE_TYPE int
|
||||||
|
|
||||||
|
const (
|
||||||
|
AllocateAnyPages EFI_ALLOCATE_TYPE = iota
|
||||||
|
AllocateMaxAddress
|
||||||
|
AllocateAddress
|
||||||
|
)
|
||||||
|
|
||||||
|
type EFI_MEMORY_TYPE int
|
||||||
|
|
||||||
|
const (
|
||||||
|
EfiReservedMemoryType EFI_MEMORY_TYPE = iota
|
||||||
|
EfiLoaderCode
|
||||||
|
EfiLoaderData
|
||||||
|
EfiBootServicesCode
|
||||||
|
EfiBootServicesData
|
||||||
|
EfiRuntimeServicesCode
|
||||||
|
EfiRuntimeServicesData
|
||||||
|
EfiConventionalMemory
|
||||||
|
)
|
||||||
|
|
||||||
|
type EVENT_TYPE uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
EVT_TIMER EVENT_TYPE = 0x80000000
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TPL_CALLBACK EFI_TPL = 8
|
||||||
|
)
|
||||||
|
|
||||||
|
type EFI_TIMER_DELAY int
|
||||||
|
|
||||||
|
const (
|
||||||
|
TimerCancel EFI_TIMER_DELAY = iota
|
||||||
|
TimerPeriodic
|
||||||
|
TimerRelative
|
||||||
|
)
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
package uefi
|
||||||
|
|
||||||
|
const (
|
||||||
|
uintnSize = 32 << (^uintptr(0) >> 63)
|
||||||
|
errorMask = 1 << uintptr(uintnSize-1)
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
EFI_SUCCESS EFI_STATUS = 0
|
||||||
|
EFI_LOAD_ERROR EFI_STATUS = errorMask | 1
|
||||||
|
EFI_INVALID_PARAMETER EFI_STATUS = errorMask | 2
|
||||||
|
EFI_UNSUPPORTED EFI_STATUS = errorMask | 3
|
||||||
|
EFI_BAD_BUFFER_SIZE EFI_STATUS = errorMask | 4
|
||||||
|
EFI_BUFFER_TOO_SMALL EFI_STATUS = errorMask | 5
|
||||||
|
EFI_NOT_READY EFI_STATUS = errorMask | 6
|
||||||
|
EFI_DEVICE_ERROR EFI_STATUS = errorMask | 7
|
||||||
|
EFI_WRITE_PROTECTED EFI_STATUS = errorMask | 8
|
||||||
|
EFI_OUT_OF_RESOURCES EFI_STATUS = errorMask | 9
|
||||||
|
EFI_VOLUME_CORRUPTED EFI_STATUS = errorMask | 10
|
||||||
|
EFI_VOLUME_FULL EFI_STATUS = errorMask | 11
|
||||||
|
EFI_NO_MEDIA EFI_STATUS = errorMask | 12
|
||||||
|
EFI_MEDIA_CHANGED EFI_STATUS = errorMask | 13
|
||||||
|
EFI_NOT_FOUND EFI_STATUS = errorMask | 14
|
||||||
|
EFI_ACCESS_DENIED EFI_STATUS = errorMask | 15
|
||||||
|
EFI_NO_RESPONSE EFI_STATUS = errorMask | 16
|
||||||
|
EFI_NO_MAPPING EFI_STATUS = errorMask | 17
|
||||||
|
EFI_TIMEOUT EFI_STATUS = errorMask | 18
|
||||||
|
EFI_NOT_STARTED EFI_STATUS = errorMask | 19
|
||||||
|
EFI_ALREADY_STARTED EFI_STATUS = errorMask | 20
|
||||||
|
EFI_ABORTED EFI_STATUS = errorMask | 21
|
||||||
|
EFI_ICMP_ERROR EFI_STATUS = errorMask | 22
|
||||||
|
EFI_TFTP_ERROR EFI_STATUS = errorMask | 23
|
||||||
|
EFI_PROTOCOL_ERROR EFI_STATUS = errorMask | 24
|
||||||
|
EFI_INCOMPATIBLE_VERSION EFI_STATUS = errorMask | 25
|
||||||
|
EFI_SECURITY_VIOLATION EFI_STATUS = errorMask | 26
|
||||||
|
EFI_CRC_ERROR EFI_STATUS = errorMask | 27
|
||||||
|
EFI_END_OF_MEDIA EFI_STATUS = errorMask | 28
|
||||||
|
EFI_END_OF_FILE EFI_STATUS = errorMask | 31
|
||||||
|
EFI_INVALID_LANGUAGE EFI_STATUS = errorMask | 32
|
||||||
|
EFI_COMPROMISED_DATA EFI_STATUS = errorMask | 33
|
||||||
|
EFI_IP_ADDRESS_CONFLICT EFI_STATUS = errorMask | 34
|
||||||
|
EFI_HTTP_ERROR EFI_STATUS = errorMask | 35
|
||||||
|
)
|
||||||
|
|
||||||
|
var errMap = map[EFI_STATUS]*Error{}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrLoadError = newError(EFI_LOAD_ERROR, "image failed to load")
|
||||||
|
ErrInvalidParameter = newError(EFI_INVALID_PARAMETER, "a parameter was incorrect")
|
||||||
|
ErrUnsupported = newError(EFI_UNSUPPORTED, "operation not supported")
|
||||||
|
ErrBadBufferSize = newError(EFI_BAD_BUFFER_SIZE, "buffer size incorrect for request")
|
||||||
|
ErrBufferTooSmall = newError(EFI_BUFFER_TOO_SMALL, "buffer too small; size returned in parameter")
|
||||||
|
ErrNotReady = newError(EFI_NOT_READY, "no data pending")
|
||||||
|
ErrDeviceError = newError(EFI_DEVICE_ERROR, "physical device reported an error")
|
||||||
|
ErrWriteProtected = newError(EFI_WRITE_PROTECTED, "device is write-protected")
|
||||||
|
ErrOutOfResources = newError(EFI_OUT_OF_RESOURCES, "out of resources")
|
||||||
|
ErrVolumeCorrupted = newError(EFI_VOLUME_CORRUPTED, "filesystem inconsistency detected")
|
||||||
|
ErrVolumeFull = newError(EFI_VOLUME_FULL, "no more space on filesystem")
|
||||||
|
ErrNoMedia = newError(EFI_NO_MEDIA, "device contains no medium")
|
||||||
|
ErrMediaChanged = newError(EFI_MEDIA_CHANGED, "medium changed since last access")
|
||||||
|
ErrNotFound = newError(EFI_NOT_FOUND, "item not found")
|
||||||
|
ErrAccessDenied = newError(EFI_ACCESS_DENIED, "access denied")
|
||||||
|
ErrNoResponse = newError(EFI_NO_RESPONSE, "server not found or no response")
|
||||||
|
ErrNoMapping = newError(EFI_NO_MAPPING, "no device mapping exists")
|
||||||
|
ErrTimeout = newError(EFI_TIMEOUT, "timeout expired")
|
||||||
|
ErrNotStarted = newError(EFI_NOT_STARTED, "protocol not started")
|
||||||
|
ErrAlreadyStarted = newError(EFI_ALREADY_STARTED, "protocol already started")
|
||||||
|
ErrAborted = newError(EFI_ABORTED, "operation aborted")
|
||||||
|
ErrICMPError = newError(EFI_ICMP_ERROR, "ICMP error during network operation")
|
||||||
|
ErrTFTPError = newError(EFI_TFTP_ERROR, "TFTP error during network operation")
|
||||||
|
ErrProtocolError = newError(EFI_PROTOCOL_ERROR, "protocol error during network operation")
|
||||||
|
ErrIncompatibleVersion = newError(EFI_INCOMPATIBLE_VERSION, "requested version incompatible")
|
||||||
|
ErrSecurityViolation = newError(EFI_SECURITY_VIOLATION, "security violation")
|
||||||
|
ErrCRCError = newError(EFI_CRC_ERROR, "CRC error detected")
|
||||||
|
ErrEndOfMedia = newError(EFI_END_OF_MEDIA, "beginning or end of media reached")
|
||||||
|
ErrEndOfFile = newError(EFI_END_OF_FILE, "end of file reached")
|
||||||
|
ErrInvalidLanguage = newError(EFI_INVALID_LANGUAGE, "invalid language specified")
|
||||||
|
ErrCompromisedData = newError(EFI_COMPROMISED_DATA, "data security status unknown or compromised")
|
||||||
|
ErrIPAddressConflict = newError(EFI_IP_ADDRESS_CONFLICT, "IP address conflict detected")
|
||||||
|
ErrHTTPError = newError(EFI_HTTP_ERROR, "HTTP error during network operation")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Error struct {
|
||||||
|
code EFI_STATUS
|
||||||
|
msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newError(code EFI_STATUS, msg string) *Error {
|
||||||
|
err := &Error{code: code, msg: msg}
|
||||||
|
errMap[code] = err
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Error) Error() string {
|
||||||
|
return e.msg
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Error) Status() EFI_STATUS {
|
||||||
|
return e.code
|
||||||
|
}
|
||||||
|
|
||||||
|
func StatusError(status EFI_STATUS) *Error {
|
||||||
|
if status == EFI_SUCCESS {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err, ok := errMap[status]
|
||||||
|
if !ok {
|
||||||
|
return newError(status, "unknown EFI error")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package uefi
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func booleanArg(v BOOLEAN) uintptr {
|
||||||
|
if v {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type EFI_SIMPLE_TEXT_OUTPUT_MODE struct {
|
||||||
|
MaxMode int32
|
||||||
|
Mode int32
|
||||||
|
Attribute int32
|
||||||
|
CursorColumn int32
|
||||||
|
CursorRow int32
|
||||||
|
CursorVisible BOOLEAN
|
||||||
|
}
|
||||||
|
|
||||||
|
type EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL struct {
|
||||||
|
reset uintptr
|
||||||
|
outputString uintptr
|
||||||
|
testString uintptr
|
||||||
|
queryMode uintptr
|
||||||
|
setMode uintptr
|
||||||
|
setAttribute uintptr
|
||||||
|
clearScreen uintptr
|
||||||
|
setCursorPosition uintptr
|
||||||
|
enableCursor uintptr
|
||||||
|
Mode *EFI_SIMPLE_TEXT_OUTPUT_MODE
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL) Reset(extendedVerification BOOLEAN) EFI_STATUS {
|
||||||
|
return UefiCall2(p.reset, uintptr(unsafe.Pointer(p)), booleanArg(extendedVerification))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL) OutputString(s *CHAR16) EFI_STATUS {
|
||||||
|
return UefiCall2(p.outputString, uintptr(unsafe.Pointer(p)), uintptr(unsafe.Pointer(s)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL) TestString(s *CHAR16) EFI_STATUS {
|
||||||
|
return UefiCall2(p.testString, uintptr(unsafe.Pointer(p)), uintptr(unsafe.Pointer(s)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL) QueryMode(modeNumber UINTN, columns *UINTN, rows *UINTN) EFI_STATUS {
|
||||||
|
return UefiCall4(
|
||||||
|
p.queryMode,
|
||||||
|
uintptr(unsafe.Pointer(p)),
|
||||||
|
uintptr(modeNumber),
|
||||||
|
uintptr(unsafe.Pointer(columns)),
|
||||||
|
uintptr(unsafe.Pointer(rows)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL) SetMode(modeNumber UINTN) EFI_STATUS {
|
||||||
|
return UefiCall2(p.setMode, uintptr(unsafe.Pointer(p)), uintptr(modeNumber))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL) SetAttribute(attribute UINTN) EFI_STATUS {
|
||||||
|
return UefiCall2(p.setAttribute, uintptr(unsafe.Pointer(p)), uintptr(attribute))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL) ClearScreen() EFI_STATUS {
|
||||||
|
return UefiCall1(p.clearScreen, uintptr(unsafe.Pointer(p)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL) SetCursorPosition(column UINTN, row UINTN) EFI_STATUS {
|
||||||
|
return UefiCall3(p.setCursorPosition, uintptr(unsafe.Pointer(p)), uintptr(column), uintptr(row))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL) EnableCursor(visible BOOLEAN) EFI_STATUS {
|
||||||
|
return UefiCall2(p.enableCursor, uintptr(unsafe.Pointer(p)), booleanArg(visible))
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
package uefi
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
type EFI_RUNTIME_SERVICES struct {
|
||||||
|
Hdr EFI_TABLE_HEADER
|
||||||
|
getTime uintptr
|
||||||
|
setTime uintptr
|
||||||
|
getWakeupTime uintptr
|
||||||
|
setWakeupTime uintptr
|
||||||
|
setVirtualAddressMap uintptr
|
||||||
|
convertPointer uintptr
|
||||||
|
getVariable uintptr
|
||||||
|
getNextVariableName uintptr
|
||||||
|
setVariable uintptr
|
||||||
|
getNextHighMonoCount uintptr
|
||||||
|
resetSystem uintptr
|
||||||
|
updateCapsule uintptr
|
||||||
|
queryCapsuleCaps uintptr
|
||||||
|
queryVariableInfo uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type EFI_BOOT_SERVICES struct {
|
||||||
|
Hdr EFI_TABLE_HEADER
|
||||||
|
raiseTPL uintptr
|
||||||
|
restoreTPL uintptr
|
||||||
|
allocatePages uintptr
|
||||||
|
freePages uintptr
|
||||||
|
getMemoryMap uintptr
|
||||||
|
allocatePool uintptr
|
||||||
|
freePool uintptr
|
||||||
|
createEvent uintptr
|
||||||
|
setTimer uintptr
|
||||||
|
waitForEvent uintptr
|
||||||
|
signalEvent uintptr
|
||||||
|
closeEvent uintptr
|
||||||
|
checkEvent uintptr
|
||||||
|
installProtocolInterface uintptr
|
||||||
|
reinstallProtocolIFace uintptr
|
||||||
|
uninstallProtocolIFace uintptr
|
||||||
|
handleProtocol uintptr
|
||||||
|
reserved *VOID
|
||||||
|
registerProtocolNotify uintptr
|
||||||
|
locateHandle uintptr
|
||||||
|
locateDevicePath uintptr
|
||||||
|
installConfigurationTable uintptr
|
||||||
|
loadImage uintptr
|
||||||
|
startImage uintptr
|
||||||
|
exit uintptr
|
||||||
|
unloadImage uintptr
|
||||||
|
exitBootServices uintptr
|
||||||
|
getNextMonotonicCount uintptr
|
||||||
|
stall uintptr
|
||||||
|
setWatchdogTimer uintptr
|
||||||
|
connectController uintptr
|
||||||
|
disconnectController uintptr
|
||||||
|
openProtocol uintptr
|
||||||
|
closeProtocol uintptr
|
||||||
|
openProtocolInformation uintptr
|
||||||
|
protocolsPerHandle uintptr
|
||||||
|
locateHandleBuffer uintptr
|
||||||
|
locateProtocol uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_BOOT_SERVICES) AllocatePages(typ EFI_ALLOCATE_TYPE, memoryType EFI_MEMORY_TYPE, pages UINTN, memory *EFI_PHYSICAL_ADDRESS) EFI_STATUS {
|
||||||
|
return UefiCall4(p.allocatePages, uintptr(typ), uintptr(memoryType), uintptr(pages), uintptr(unsafe.Pointer(memory)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_BOOT_SERVICES) FreePages(memory EFI_PHYSICAL_ADDRESS, pages UINTN) EFI_STATUS {
|
||||||
|
return UefiCall2(p.freePages, uintptr(memory), uintptr(pages))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_BOOT_SERVICES) CreateEvent(typ EVENT_TYPE, notifyTPL EFI_TPL, notifyFunction unsafe.Pointer, notifyContext unsafe.Pointer, event *EFI_EVENT) EFI_STATUS {
|
||||||
|
return UefiCall5(p.createEvent, uintptr(typ), uintptr(notifyTPL), uintptr(notifyFunction), uintptr(notifyContext), uintptr(unsafe.Pointer(event)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_BOOT_SERVICES) SetTimer(event EFI_EVENT, typ EFI_TIMER_DELAY, triggerTime uint64) EFI_STATUS {
|
||||||
|
return UefiCall3(p.setTimer, uintptr(event), uintptr(typ), uintptr(triggerTime))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_BOOT_SERVICES) WaitForEvent(numberOfEvents UINTN, event *EFI_EVENT, index *UINTN) EFI_STATUS {
|
||||||
|
return UefiCall3(p.waitForEvent, uintptr(numberOfEvents), uintptr(unsafe.Pointer(event)), uintptr(unsafe.Pointer(index)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_BOOT_SERVICES) CloseEvent(event EFI_EVENT) EFI_STATUS {
|
||||||
|
return UefiCall1(p.closeEvent, uintptr(event))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_BOOT_SERVICES) CheckEvent(event EFI_EVENT) EFI_STATUS {
|
||||||
|
return UefiCall1(p.checkEvent, uintptr(event))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_BOOT_SERVICES) HandleProtocol(handle EFI_HANDLE, protocol *EFI_GUID, iface unsafe.Pointer) EFI_STATUS {
|
||||||
|
return UefiCall3(p.handleProtocol, uintptr(handle), uintptr(unsafe.Pointer(protocol)), uintptr(iface))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_BOOT_SERVICES) LocateProtocol(protocol *EFI_GUID, registration *VOID, iface unsafe.Pointer) EFI_STATUS {
|
||||||
|
return UefiCall3(p.locateProtocol, uintptr(unsafe.Pointer(protocol)), uintptr(unsafe.Pointer(registration)), uintptr(iface))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_BOOT_SERVICES) Exit(imageHandle EFI_HANDLE, exitStatus EFI_STATUS, exitDataSize UINTN, exitData *CHAR16) EFI_STATUS {
|
||||||
|
return UefiCall4(p.exit, uintptr(imageHandle), uintptr(exitStatus), uintptr(exitDataSize), uintptr(unsafe.Pointer(exitData)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EFI_BOOT_SERVICES) SetWatchdogTimer(timeout UINTN, watchdogCode uint64, dataSize UINTN, watchdogData *CHAR16) EFI_STATUS {
|
||||||
|
return UefiCall4(p.setWatchdogTimer, uintptr(timeout), uintptr(watchdogCode), uintptr(dataSize), uintptr(unsafe.Pointer(watchdogData)))
|
||||||
|
}
|
||||||
|
|
||||||
|
type EFI_SYSTEM_TABLE struct {
|
||||||
|
Hdr EFI_TABLE_HEADER
|
||||||
|
FirmwareVendor *CHAR16
|
||||||
|
FirmwareRevision uint32
|
||||||
|
ConsoleInHandle EFI_HANDLE
|
||||||
|
ConIn *VOID
|
||||||
|
ConsoleOutHandle EFI_HANDLE
|
||||||
|
ConOut *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
|
||||||
|
StandardErrorHandle EFI_HANDLE
|
||||||
|
StdErr *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
|
||||||
|
RuntimeServices *EFI_RUNTIME_SERVICES
|
||||||
|
BootServices *EFI_BOOT_SERVICES
|
||||||
|
NumberOfTableEntries UINTN
|
||||||
|
ConfigurationTable *VOID
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package uefi
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var errNilTextOutputProtocol = errors.New("uefi: nil simple text output protocol")
|
||||||
|
|
||||||
|
type TextOutput struct {
|
||||||
|
proto *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTextOutput(proto *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL) *TextOutput {
|
||||||
|
return &TextOutput{proto: proto}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConsoleOut() *TextOutput {
|
||||||
|
return NewTextOutput(ST().ConOut)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StandardError() *TextOutput {
|
||||||
|
return NewTextOutput(ST().StdErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *TextOutput) Write(p []byte) (int, error) {
|
||||||
|
if w == nil || w.proto == nil {
|
||||||
|
return 0, errNilTextOutputProtocol
|
||||||
|
}
|
||||||
|
if len(p) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := StringToCHAR16Z(string(p))
|
||||||
|
status := w.proto.OutputString(&buf[0])
|
||||||
|
if status != EFI_SUCCESS {
|
||||||
|
return 0, StatusError(status)
|
||||||
|
}
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *TextOutput) WriteString(s string) (int, error) {
|
||||||
|
return w.Write([]byte(s))
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
//go:build uefi
|
||||||
|
|
||||||
|
package uefi
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
var systemTable *EFI_SYSTEM_TABLE
|
||||||
|
var imageHandle uintptr
|
||||||
|
|
||||||
|
//go:nobounds
|
||||||
|
func Init(argImageHandle uintptr, argSystemTable uintptr) {
|
||||||
|
systemTable = (*EFI_SYSTEM_TABLE)(unsafe.Pointer(argSystemTable))
|
||||||
|
imageHandle = argImageHandle
|
||||||
|
}
|
||||||
|
|
||||||
|
func ST() *EFI_SYSTEM_TABLE {
|
||||||
|
return systemTable
|
||||||
|
}
|
||||||
|
|
||||||
|
func BS() *EFI_BOOT_SERVICES {
|
||||||
|
if systemTable == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return systemTable.BootServices
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImageHandle() EFI_HANDLE {
|
||||||
|
return EFI_HANDLE(imageHandle)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user