add device/uefi and device/amd64

This commit is contained in:
Matthew Hiles
2026-06-15 14:45:37 -04:00
committed by Ron Evans
parent bd61913973
commit 0922e3e956
13 changed files with 936 additions and 0 deletions
+74
View File
@@ -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)
}
+39
View File
@@ -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
+17
View File
@@ -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()
}
+201
View File
@@ -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
+45
View File
@@ -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
+77
View File
@@ -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))
}
+39
View File
@@ -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
}
+66
View File
@@ -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
)
+111
View File
@@ -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
}
+74
View File
@@ -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))
}
+123
View File
@@ -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
}
+41
View File
@@ -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))
}
+29
View File
@@ -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)
}