-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
targets: minimal uefi target support #5452
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
deadprogram
merged 34 commits into
tinygo-org:dev
from
sparques:pr/minimal-uefi-target-support
Jul 23, 2026
Merged
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
b8a8e70
runtime: split baremetal memory setup
sparques e906cf7
runtime: extract Windows PE globals scan helper
sparques 36d6c7c
compileopts,builder: add target linker flavor override
sparques 2ad1004
machine,runtime,targets: add minimal uefi-amd64 target
sparques 0d905c1
runtime,examples: add clean UEFI exit path test
sparques 6ad501d
machine,x86: fix amd64 ABI stack handling
sparques 2929a18
machine/uefi: add CHAR16 conversion helpers
sparques da76f63
machine/uefi: add loaded image protocol support
sparques f0cc366
runtime: add UEFI PE globals support
sparques 84dd7a9
machine,runtime,x86: add UEFI time and text output support
sparques 1cb0280
machine,runtime,x86: add UEFI text and time support
sparques 408bfbb
machine,runtime,examples: add UEFI text input support
sparques 308a0ff
machine,examples: add UEFI graphics output support
sparques 8a7f085
add rest of STOP methods (direct UEFI ABI only)
sparques f62bc0e
runtime: fix UEFI sleep tick conversion
sparques d108e99
machine/uefi: make text input waits cooperative
sparques d13ac22
Merge remote-tracking branch 'upstream/dev' into feat/uefi-restack
sparques a38dd8d
Merge remote-tracking branch 'upstream/dev' into feat/uefi-restack
sparques 43029f5
address TestClangAttributes/uefi-amd64 failure
sparques c552153
address TestConfigLinkerFlavor bug
sparques 119691c
uefi: move raw bindings to device package
sparques cc08fe5
strip down implementation to bare minimum
sparques 145969f
Merge branch 'dev' into pr/minimal-uefi-target-support
sparques 5d19dd9
amd64: rename x86 package
sparques cd09e82
Merge branch 'pr/minimal-uefi-target-support' of ssh://github.com/spa…
sparques 4ea5256
Merge branch 'dev' into pr/minimal-uefi-target-support
sparques a3645f0
Merge branch 'dev' of ssh://github.com/tinygo-org/tinygo into pr/mini…
sparques 3dc2ddf
Merge branch 'pr/minimal-uefi-target-support' of ssh://github.com/spa…
sparques 031b449
do git restore upstream/dev for src/net
sparques 72a0116
Merge branch 'dev' of ssh://github.com/tinygo-org/tinygo into pr/mini…
sparques 19d9e67
add smoketest for uefi-amd64; add required zeroSizeAllocPtr constant
sparques 1659813
address PR issues: remove unused files; make putchar() insert '\r' be…
sparques 4a11f0b
swap lines around
sparques 99f8a6e
Merge branch 'dev' of ssh://github.com/tinygo-org/tinygo into pr/mini…
sparques File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| //go:build uefi | ||
|
|
||
| package machine | ||
|
|
||
| import ( | ||
| deviceuefi "device/uefi" | ||
| ) | ||
|
|
||
| const deviceName = "UEFI" | ||
|
|
||
| type ( | ||
| EFI_STATUS = deviceuefi.EFI_STATUS | ||
| TextOutput = deviceuefi.TextOutput | ||
|
|
||
| Error = deviceuefi.Error | ||
| ) | ||
|
|
||
| const ( | ||
| EFI_SUCCESS = deviceuefi.EFI_SUCCESS | ||
| EFI_LOAD_ERROR = deviceuefi.EFI_LOAD_ERROR | ||
| EFI_INVALID_PARAMETER = deviceuefi.EFI_INVALID_PARAMETER | ||
| EFI_UNSUPPORTED = deviceuefi.EFI_UNSUPPORTED | ||
| EFI_BAD_BUFFER_SIZE = deviceuefi.EFI_BAD_BUFFER_SIZE | ||
| EFI_BUFFER_TOO_SMALL = deviceuefi.EFI_BUFFER_TOO_SMALL | ||
| EFI_NOT_READY = deviceuefi.EFI_NOT_READY | ||
| EFI_DEVICE_ERROR = deviceuefi.EFI_DEVICE_ERROR | ||
| EFI_WRITE_PROTECTED = deviceuefi.EFI_WRITE_PROTECTED | ||
| EFI_OUT_OF_RESOURCES = deviceuefi.EFI_OUT_OF_RESOURCES | ||
| EFI_VOLUME_CORRUPTED = deviceuefi.EFI_VOLUME_CORRUPTED | ||
| EFI_VOLUME_FULL = deviceuefi.EFI_VOLUME_FULL | ||
| EFI_NO_MEDIA = deviceuefi.EFI_NO_MEDIA | ||
| EFI_MEDIA_CHANGED = deviceuefi.EFI_MEDIA_CHANGED | ||
| EFI_NOT_FOUND = deviceuefi.EFI_NOT_FOUND | ||
| EFI_ACCESS_DENIED = deviceuefi.EFI_ACCESS_DENIED | ||
| EFI_NO_RESPONSE = deviceuefi.EFI_NO_RESPONSE | ||
| EFI_NO_MAPPING = deviceuefi.EFI_NO_MAPPING | ||
| EFI_TIMEOUT = deviceuefi.EFI_TIMEOUT | ||
| EFI_NOT_STARTED = deviceuefi.EFI_NOT_STARTED | ||
| EFI_ALREADY_STARTED = deviceuefi.EFI_ALREADY_STARTED | ||
| EFI_ABORTED = deviceuefi.EFI_ABORTED | ||
| EFI_ICMP_ERROR = deviceuefi.EFI_ICMP_ERROR | ||
| EFI_TFTP_ERROR = deviceuefi.EFI_TFTP_ERROR | ||
| EFI_PROTOCOL_ERROR = deviceuefi.EFI_PROTOCOL_ERROR | ||
| EFI_INCOMPATIBLE_VERSION = deviceuefi.EFI_INCOMPATIBLE_VERSION | ||
| EFI_SECURITY_VIOLATION = deviceuefi.EFI_SECURITY_VIOLATION | ||
| EFI_CRC_ERROR = deviceuefi.EFI_CRC_ERROR | ||
| EFI_END_OF_MEDIA = deviceuefi.EFI_END_OF_MEDIA | ||
| EFI_END_OF_FILE = deviceuefi.EFI_END_OF_FILE | ||
| EFI_INVALID_LANGUAGE = deviceuefi.EFI_INVALID_LANGUAGE | ||
| EFI_COMPROMISED_DATA = deviceuefi.EFI_COMPROMISED_DATA | ||
| EFI_IP_ADDRESS_CONFLICT = deviceuefi.EFI_IP_ADDRESS_CONFLICT | ||
| EFI_HTTP_ERROR = deviceuefi.EFI_HTTP_ERROR | ||
| ) | ||
|
|
||
| var ( | ||
| ErrLoadError = deviceuefi.ErrLoadError | ||
| ErrInvalidParameter = deviceuefi.ErrInvalidParameter | ||
| ErrUnsupported = deviceuefi.ErrUnsupported | ||
| ErrBadBufferSize = deviceuefi.ErrBadBufferSize | ||
| ErrBufferTooSmall = deviceuefi.ErrBufferTooSmall | ||
| ErrNotReady = deviceuefi.ErrNotReady | ||
| ErrDeviceError = deviceuefi.ErrDeviceError | ||
| ErrWriteProtected = deviceuefi.ErrWriteProtected | ||
| ErrOutOfResources = deviceuefi.ErrOutOfResources | ||
| ErrVolumeCorrupted = deviceuefi.ErrVolumeCorrupted | ||
| ErrVolumeFull = deviceuefi.ErrVolumeFull | ||
| ErrNoMedia = deviceuefi.ErrNoMedia | ||
| ErrMediaChanged = deviceuefi.ErrMediaChanged | ||
| ErrNotFound = deviceuefi.ErrNotFound | ||
| ErrAccessDenied = deviceuefi.ErrAccessDenied | ||
| ErrNoResponse = deviceuefi.ErrNoResponse | ||
| ErrNoMapping = deviceuefi.ErrNoMapping | ||
| ErrTimeout = deviceuefi.ErrTimeout | ||
| ErrNotStarted = deviceuefi.ErrNotStarted | ||
| ErrAlreadyStarted = deviceuefi.ErrAlreadyStarted | ||
| ErrAborted = deviceuefi.ErrAborted | ||
| ErrICMPError = deviceuefi.ErrICMPError | ||
| ErrTFTPError = deviceuefi.ErrTFTPError | ||
| ErrProtocolError = deviceuefi.ErrProtocolError | ||
| ErrIncompatibleVersion = deviceuefi.ErrIncompatibleVersion | ||
| ErrSecurityViolation = deviceuefi.ErrSecurityViolation | ||
| ErrCRCError = deviceuefi.ErrCRCError | ||
| ErrEndOfMedia = deviceuefi.ErrEndOfMedia | ||
| ErrEndOfFile = deviceuefi.ErrEndOfFile | ||
| ErrInvalidLanguage = deviceuefi.ErrInvalidLanguage | ||
| ErrCompromisedData = deviceuefi.ErrCompromisedData | ||
| ErrIPAddressConflict = deviceuefi.ErrIPAddressConflict | ||
| ErrHTTPError = deviceuefi.ErrHTTPError | ||
| ) | ||
|
|
||
| func ConsoleOut() *TextOutput { | ||
| return deviceuefi.ConsoleOut() | ||
| } | ||
|
|
||
| func StandardError() *TextOutput { | ||
| return deviceuefi.StandardError() | ||
| } | ||
|
|
||
| func StatusError(status EFI_STATUS) *Error { | ||
| return deviceuefi.StatusError(status) | ||
| } | ||
|
|
||
| func (Pin) Configure(PinConfig) { | ||
| } | ||
|
|
||
| func (Pin) Set(bool) { | ||
| } | ||
|
|
||
| func (Pin) Get() bool { | ||
| return false | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| //go:build baremetal | ||
| //go:build baremetal && !uefi | ||
|
|
||
| package runtime | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| //go:build baremetal || tinygo.wasm | ||
| //go:build (baremetal || tinygo.wasm) && !uefi | ||
|
|
||
| package runtime | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| //go:build gc.leaking && uefi | ||
|
|
||
| package runtime | ||
|
|
||
| import _ "unsafe" | ||
|
|
||
| //go:export tinygo_scanstack | ||
| func tinygo_scanstack() { | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| //go:build !baremetal || tkey | ||
| //go:build !baremetal || tkey || uefi | ||
|
|
||
| package interrupt | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| //go:build windows | ||
| //go:build windows || uefi | ||
|
|
||
| package runtime | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| //go:build uefi | ||
|
|
||
| package runtime | ||
|
|
||
| import "device/uefi" | ||
|
|
||
| const zeroSizeAllocPtr uintptr = 16 | ||
|
|
||
| //go:linkname procPin sync/atomic.runtime_procPin | ||
| func procPin() { | ||
| } | ||
|
|
||
| //go:linkname procUnpin sync/atomic.runtime_procUnpin | ||
| func procUnpin() { | ||
| } | ||
|
|
||
| var heapSize uintptr = 64 * 1024 * 1024 | ||
| var heapStart, heapEnd uintptr | ||
| var stackTop uintptr | ||
| var allocatePagesAddress uefi.EFI_PHYSICAL_ADDRESS | ||
| var waitForEventsFunction = func() { | ||
| uefi.CpuPause() | ||
| } | ||
|
|
||
| func ticks() timeUnit { | ||
| return timeUnit(uefi.Ticks()) | ||
| } | ||
|
|
||
| func nanosecondsToTicks(ns int64) timeUnit { | ||
| frequency := int64(uefi.TicksFrequency()) | ||
| if frequency == 0 { | ||
| return timeUnit(ns) | ||
| } | ||
| seconds := ns / 1000000000 | ||
| remainder := ns % 1000000000 | ||
| return timeUnit(seconds*frequency + (remainder*frequency)/1000000000) | ||
| } | ||
|
|
||
| func ticksToNanoseconds(t timeUnit) int64 { | ||
| frequency := int64(uefi.TicksFrequency()) | ||
| if frequency == 0 { | ||
| return int64(t) | ||
| } | ||
| return int64(t) * 1000000000 / frequency | ||
| } | ||
|
|
||
| func sleepTicks(d timeUnit) { | ||
| if d == 0 { | ||
| return | ||
| } | ||
| end := ticks() + d | ||
| for ticks() < end { | ||
| uefi.CpuPause() | ||
| } | ||
| } | ||
|
|
||
| func putchar(c byte) { | ||
| if c == '\n' { | ||
| buf := [4]uefi.CHAR16{'\r', 0, '\n', 0} | ||
| uefi.ST().ConOut.OutputString(&buf[0]) | ||
| return | ||
| } | ||
| buf := [2]uefi.CHAR16{uefi.CHAR16(c), 0} | ||
| uefi.ST().ConOut.OutputString(&buf[0]) | ||
| } | ||
|
|
||
| func exit(code int) { | ||
| uefi.BS().Exit(uefi.GetImageHandle(), uefi.EFI_STATUS(code), 0, nil) | ||
| } | ||
|
|
||
| func abort() { | ||
| uefi.BS().Exit(uefi.GetImageHandle(), uefi.EFI_ABORTED, 0, nil) | ||
| } | ||
|
|
||
| func preinit() { | ||
| uefi.BS().SetWatchdogTimer(0, 0, 0, nil) | ||
| if !growHeap() { | ||
| runtimePanic("could not allocate initial UEFI heap") | ||
| } | ||
| } | ||
|
|
||
| func growHeap() bool { | ||
| newHeapSize := ((heapSize * 4) / 3) &^ 4095 | ||
| for newHeapSize >= heapSize { | ||
| pages := newHeapSize / 4096 | ||
| status := uefi.BS().AllocatePages( | ||
| uefi.AllocateAnyPages, | ||
| uefi.EfiLoaderData, | ||
| uefi.UINTN(pages), | ||
| &allocatePagesAddress, | ||
| ) | ||
| if status == uefi.EFI_SUCCESS { | ||
| heapStart = uintptr(allocatePagesAddress) | ||
| heapSize = newHeapSize | ||
| setHeapEnd(heapStart + heapSize) | ||
| return true | ||
| } | ||
| if status != uefi.EFI_OUT_OF_RESOURCES { | ||
| return false | ||
| } | ||
| newHeapSize /= 2 | ||
| } | ||
| return false | ||
| } | ||
|
|
||
| func SetWaitForEvents(f func()) { | ||
| waitForEventsFunction = f | ||
| } | ||
|
|
||
| func waitForEvents() { | ||
| waitForEventsFunction() | ||
| } | ||
|
|
||
| //go:noinline | ||
| func runMain() { | ||
| run() | ||
| } | ||
|
|
||
| func buffered() int { | ||
| return 0 | ||
| } | ||
|
|
||
| func getchar() byte { | ||
| return 0 | ||
| } | ||
|
|
||
| //export efi_main | ||
| func main(imageHandle uintptr, systemTable uintptr) uintptr { | ||
| uefi.Init(imageHandle, systemTable) | ||
| preinit() | ||
| stackTop = getCurrentStackPointer() | ||
| runMain() | ||
|
|
||
| if heapStart != 0 { | ||
| uefi.BS().FreePages(uefi.EFI_PHYSICAL_ADDRESS(heapStart), uefi.UINTN(heapSize/4096)) | ||
| } | ||
|
|
||
| return 0 | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| //go:build !(scheduler.tasks && uefi) | ||
|
|
||
| package runtime | ||
|
|
||
| func schedulerSleepCustom(duration int64) bool { | ||
| return false | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| { | ||
| "build-tags": ["uefi", "baremetal", "linux", "amd64"], | ||
| "llvm-target": "x86_64-unknown-windows-gnu", | ||
| "cpu": "x86-64", | ||
| "features": "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87", | ||
| "goos": "linux", | ||
| "goarch": "amd64", | ||
| "gc": "leaking", | ||
| "scheduler": "none", | ||
| "linker": "ld.lld", | ||
| "linker-flavor": "coff", | ||
| "libc": "picolibc", | ||
| "automatic-stack-size": false, | ||
| "default-stack-size": 65536, | ||
| "cflags": [ | ||
| "-Werror", | ||
| "-fshort-enums", | ||
| "-fomit-frame-pointer", | ||
| "-fno-exceptions", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables", | ||
| "-ffunction-sections", "-fdata-sections", | ||
| "-ffreestanding", | ||
| "-fshort-wchar", | ||
| "-mno-red-zone" | ||
| ], | ||
| "ldflags": [ | ||
| "-m", "i386pep", | ||
| "--image-base", "0x400000", | ||
| "--entry", "efi_main", | ||
| "--subsystem", "efi_application", | ||
| "-Bdynamic", | ||
| "--gc-sections", | ||
| "--no-insert-timestamp", | ||
| "--no-dynamicbase" | ||
| ], | ||
| "extra-files": [ | ||
| "src/device/amd64/cpu_amd64.S", | ||
| "src/device/uefi/asm_amd64.S", | ||
| "src/runtime/asm_amd64_windows.S" | ||
| ], | ||
| "gdb": ["gdb-multiarch", "gdb"] | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.