Skip to content

Conversation

jclab-joseph
Copy link

@jclab-joseph jclab-joseph commented Nov 13, 2023

Adds support for UEFI OS.

  • Working minimal
  • findGlobals
  • Refactoring
  • exit
  • amd64
  • smoke test
  • target.json

not goal

  • i386
  • arm64 (TODO)

Usage :

tinygo build -target uefi-amd64 -o test.efi main.go

image

Copy link
Member

@aykevl aykevl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a quick pass over the code (not a full review).

My main comment is this: can you make this more like any other baremetal target instead of making it its own thing besides baremetal and regular OSes? A baremetal target is much easier to maintain than what you have here (for example, the existing Nintendo Switch support is more work than any weird chip someone added support for years ago).

Also, please add a smoke test so we can see how it works.

Copy link
Member

@aykevl aykevl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it will be a huge PR, so I suggest working on ways to simplify it. It can only be merged if it is maintainable, and right now it's so invasive I honestly don't want to merge it like this.

  • Don't copy code like you did for findGlobals. Instead, find ways to reuse it. For example, you can move it to a new gc_windows.go file that is compiled in both Windows and UEFI.
  • Do not make this a new GOOS. Instead, create targets/uefi.json that sets all the necessary properties (and adds at least the uefi and baremetal build tags). This probably means using GOOS=linux, like all the other baremetal targets. Then you can compile for UEFI using tinygo build -target=uefi ....
  • Add a smoke test to GNUmakefile (there are lots of smoke tests already in there).

(To be clear: there is a difference between big and invasive. Right now it modifies many parts that shouldn't need to be modified by a PR that adds a new build target. If you need to use many lines of code to implement UEFI support, that's fine as long as it doesn't affect the common code too much).

@jclab-joseph
Copy link
Author

jclab-joseph commented Nov 20, 2023

Yes, it's not a good looking code right now.
It's a work in progress and needs a lot of refactoring.
Your opinion will help me a lot!

GOOS=linux is required, but with the exception uefi should use task_stack_windows_amd64 instead of task_stack_linux_amd64 . Cannot change name of task_stack.s without changing target.go.
I'm sorry. It was my mistake. It's being edited.

@jclab-joseph jclab-joseph changed the title WIP: Support UEFI OS Support UEFI OS Nov 21, 2023
@deadprogram deadprogram requested a review from aykevl December 30, 2023 09:57
@xplshn
Copy link

xplshn commented Apr 29, 2025

Any progress?

@jclab-joseph
Copy link
Author

@xplshn
Oh, I haven't had time to work on it any more lately.. 😿

@xplshn
Copy link

xplshn commented Apr 29, 2025

@xplshn Oh, I haven't had time to work on it any more lately.. 😿

That's okay, it's great work anyways, someone could use it as starting point to continue the port.

@jclab-joseph
Copy link
Author

FYI, here's a similar project: https://github.com/usbarmory/go-boot/

@sparques
Copy link
Contributor

I've been working on a fork of this: https://github.com/sparques/tinygo/tree/feat/uefi

Most notably, I fixed the assembly shim code to correctly implement the PE calling ABI and verified it works in qemu and on real hardware. Prior to the fix, "Hello World" would not run on real hardware.

I was getting crashes when trying to use -gc=precise and -scheduler=tasks and fixed that as well. I added (possibly even correctly) support for -gc=leaking and -scheduler=none.

I've also added support for Graphics Output Protocol and have seperate driver code so the screen can be drawn to via the draw.Image interface. I have my terminal emulator working (output, at least) as an EFI application.

I'm not sure Simple Text Input Protocol (essentially , os.Stdin) is working correctly so I'm fixing that next. I also plan on adding support for Serial IO Protocol, File Protocol, and Network Protocols in that order.

@aykevl: What other clean up or reoganization is needed?

Also, where should seperate driver code go? Is tinygo.org/x/drivers/uefi/ appropriate? For example, the driver that lets you wrap a Graphics Output Protocol object into one that implements draw.Image can't live in machine/ or runtime/ because of cyclic dependencies, so I was thinking tinygo.org/x/drivers/uefi/image made sense.

@jclab-joseph
Copy link
Author

@sparques Awesome! Thank you so much for your contribution. I look forward to seeing tinygo used in uefi in the future!

@aykevl
Copy link
Member

aykevl commented Oct 4, 2025

What I'm looking for is something that is somewhat minimal (ask in, not too many lines of code changed) and fits in with the rest of TinyGo. Something that has a minimum (or ideally zero) compiler changes. In other words, something that is easy to maintain.

You gave a link to a branch, but that doesn't give me a diff. So I can't easily review that.

@xplshn
Copy link

xplshn commented Oct 5, 2025

I've been working on a fork of this: https://github.com/sparques/tinygo/tree/feat/uefi

Most notably, I fixed the assembly shim code to correctly implement the PE calling ABI and verified it works in qemu and on real hardware. Prior to the fix, "Hello World" would not run on real hardware.

I was getting crashes when trying to use -gc=precise and -scheduler=tasks and fixed that as well. I added (possibly even correctly) support for -gc=leaking and -scheduler=none.

I've also added support for Graphics Output Protocol and have seperate driver code so the screen can be drawn to via the draw.Image interface. I have my terminal emulator working (output, at least) as an EFI application.

I'm not sure Simple Text Input Protocol (essentially , os.Stdin) is working correctly so I'm fixing that next. I also plan on adding support for Serial IO Protocol, File Protocol, and Network Protocols in that order.

@aykevl: What other clean up or reoganization is needed?

Also, where should seperate driver code go? Is tinygo.org/x/drivers/uefi/ appropriate? For example, the driver that lets you wrap a Graphics Output Protocol object into one that implements draw.Image can't live in machine/ or runtime/ because of cyclic dependencies, so I was thinking tinygo.org/x/drivers/uefi/image made sense.

You should create a pull request (release...sparques:tinygo:feat/uefi)

And link it here so that @aykevl can check the diff

NOTE: @aykevl you can already review at: release...sparques:tinygo:feat/uefi

@sparques
Copy link
Contributor

sparques commented Oct 6, 2025

I created a draft PR: #5060

I'm having trouble running the tests / figuring out what I need to fix for the tests.

I did add support for several other UEFI protocols like Serial IO Protocol and the like, however I could not get it working in a VM or on real hardware and I'm not entirely sure that's my shortcomming--turns out while the UEFI spec is very thorough and featureful, basically no vendor fully implements it, making a UEFI target slightly less useful. But all the basics work and with enough unsafe.Pointer usage you can poke around other bits of hardware on a machine-by-machine basis.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants