Skip to content

Instantly share code, notes, and snippets.

@irth

irth/ovmf.fd.md Secret

Last active July 21, 2024 14:54
Show Gist options
  • Save irth/e588c081003d9655af277a63cb64dd5a to your computer and use it in GitHub Desktop.
Save irth/e588c081003d9655af277a63cb64dd5a to your computer and use it in GitHub Desktop.

backstory: we were thinking what's the worst way to get OVMF.fd (EDK II based UEFI firmware files for virtual machines), besides compiling

previous suggestions were

nix build --no-link --print-out-paths nixpkgs#OVMF.fd
it is available in the nix cache, I'm not sure how you'd download it without the package though

docker run -ti 'nixery.dev/shell/ovmf.fd'

(nixery is a magical docker registry, which builds container images out of nix packages for you on the fly)

then I suggested

N=https://nixery.dev/v2/shell/OVMF.fd; curl $N/blobs/$(curl $N/manifests/latest | jq -r '.layers[-1].digest') | tar --strip-components 1 -xvf - FV/OVMF.fd

which should try to get the last layer of the docker container and extract the file from there

but while working on the solution described below I noticed that doesn't even work (the file is a symlink to a previous layer)

i wanted to port that oneliner to browser js, but nixery.dev has CORS

so... lo and behold


https://ovmfer.pi-wo.pl/ works extremely slow

but is 700% stupid

sometimes it takes 3 minutes sometimes 20 seconds sometimes it never finishes but i dont wanna debug

basically I wanted to do what that onleiner does, download the topmost layer of the nixery.dev/shell/ovmf.fd container and extract ze files from there, but in the browser

however, CORS

but I remembered that jslinux has internet access somehow, so I checked and there's a websocket proxy for that not protected by CORS

so I could use that to make requests to nixery.dev

but the websocket sends/receives raw ethernet frames

so I wrote a rust thingy which compiles to wasm and uses smoltcp to get an IP address over DHCP, and then using rustls and rustls-rustcrypto it connects to nixery.dev

then i just send a hand written HTTP request and wait for the response, it is really slow but I don't wanna debug

then I wanted to unpack the downloaded file, there's a library in js that handles tar.gzs, turns out it failed

I think it's because it doesn't support symlinks

so I exported another function from rust, which was supposed to unpack the files using the tar crate

but the files, when extracted, were 0 bytes long

turns out the OVMF.fd files in that layer are symlinks, so useless

but

they were symlinks to /nix/store paths

so I sent over the nix paths over to the javascript side

so I could extract the hash of the derivation or whatever they call it

and apparently https://cache.nixos.org allows cross origin requests

so I fetched https://cache.nixos.org/0dvjhgpw89739l61dm69k4h4x50qgrwl.narinfo (with the hash from previous steps)

extracted the url (URL: nar/11vfij0919r75amppcdabkk4mvrizn6v1rqwnl4i5sf9d03h0vrr.nar.xz)

and learned about the existence of .nar.xz, nix has a custom archive format

I looked for rust impls of it, found two, one abandoned, one didn't work in WASM because of some filesystem related stuff

so I git clone'd it and ripped out the stuff that's unsupported in browser

and exported another function from rust, this time it extracted all the OVMF*.fd files from the .nar archive and send the name and bytes to JS

and then the JS just downloads them upon receiving

testimonials:

@irth as the original author of smoltcp i approve

~ https://mastodon.social/@whitequark/112537241341411570


I hate this
Good job
if it makes you feel any better this takes only like 15 seconds on my machine
This is amazing
the more I look at it the more I hate/love it
I feel like I could write a blog post about the lever of fuckery going on here

~ mae


image

~ Hubert

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment