Skip to content

Commit b094db9

Browse files
Bundle UEFI firmware for x86-64 QEMU
1 parent 1fcd087 commit b094db9

File tree

4 files changed

+128
-99
lines changed

4 files changed

+128
-99
lines changed

.github/workflows/bundle.yml

+20
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,35 @@ jobs:
4545
env:
4646
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4747

48+
get_ovmf_uefi_file:
49+
name: Get OVMF UEFI files
50+
runs-on: ubuntu-latest
51+
container: alpine
52+
steps:
53+
- name: Install OVMF
54+
run: apk add ovmf --no-cache
55+
56+
- name: Persist OVMF file
57+
uses: actions/upload-artifact@v4
58+
with:
59+
name: ovmf_file
60+
path: /usr/share/OVMF/OVMF.fd
61+
retention-days: 1
62+
4863
build_qemu_macos:
4964
name: Build QEMU on macOS
5065
runs-on: macos-11
66+
needs: [get_ovmf_uefi_file]
5167
steps:
5268
- name: Clone Repository
5369
uses: actions/checkout@v3
5470
with:
5571
persist-credentials: false
5672

73+
- uses: actions/download-artifact@v4
74+
with:
75+
name: ovmf_file
76+
5777
- name: Run CI Script
5878
run: ./ci.rb
5979

changelog.md

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
* Bundle QEMU UEFI for x86-64
6+
57
## 0.9.1
68

79
### Bugs Fixed:

ci.rb

+104-96
Original file line numberDiff line numberDiff line change
@@ -243,52 +243,13 @@ def ldflags
243243
end
244244

245245
def libslirp
246-
@libslirp ||= Libslirp.new
246+
ci_runner.host.libslirp
247247
end
248248

249249
def enabled_architectures
250250
@enabled_architectures ||=
251251
ci_runner.enabled_architectures.map { _1.new(self) }
252252
end
253-
254-
class Libslirp
255-
def build
256-
Dir.chdir(temp_dir) do
257-
fetch
258-
_build
259-
end
260-
end
261-
262-
def ldflags
263-
[File.join(target_path, "build", "libslirp.a")]
264-
end
265-
266-
def cleanup
267-
FileUtils.remove_entry(temp_dir)
268-
end
269-
270-
private
271-
272-
def temp_dir
273-
@temp_dir ||= Dir.mktmpdir
274-
end
275-
276-
def target_path
277-
@target_path ||= File.join(temp_dir, "libslirp-master")
278-
end
279-
280-
def fetch
281-
download_file("https://gitlab.com/qemu-project/libslirp/-/archive/master/libslirp-master.tar", "libslirp.tar")
282-
execute "tar", "-xf", "libslirp.tar"
283-
end
284-
285-
def _build
286-
Dir.chdir(target_path) do
287-
execute "meson", "setup", "-Ddefault_library=static", "build"
288-
execute "ninja", "-C", "build", "install"
289-
end
290-
end
291-
end
292253
end
293254

294255
class CIRunner
@@ -297,7 +258,6 @@ def run
297258
qemu.fetch
298259
qemu.build
299260
bundle_resources
300-
host.xhyve.install
301261
host.xhyve.bundle
302262
qemu.bundle
303263
end
@@ -322,15 +282,15 @@ def qemu_ldflags
322282
host.qemu.ldflags
323283
end
324284

325-
private
326-
327285
def host
328286
@host ||= begin
329287
os = Gem::Platform.local.os
330288
host_map[os]&.new or raise "Unsupported operating system: #{os}"
331289
end
332290
end
333291

292+
private
293+
334294
def host_map
335295
{
336296
"darwin" => MacOS,
@@ -376,12 +336,51 @@ def xhyve
376336
end
377337
end
378338

339+
def libslirp
340+
@libslirp ||= Libslirp.new
341+
end
342+
343+
def bundle_uefi(firmware_target_dir)
344+
FileUtils.cp "OVMF.fd", File.join(firmware_target_dir, "uefi.fd")
345+
end
346+
379347
def install_prerequisite
380-
packages = %w[ninja pixman glib meson]
348+
packages = %w[ninja pixman glib meson libslirp]
381349
execute "brew", "install", *packages, env: { HOMEBREW_NO_INSTALL_CLEANUP: true }
382-
end
350+
patch_glib_python_codegen
351+
end
352+
353+
# Python 3.12 doesn't have the distutils module.
354+
# Remove when updating to a version of glib newer than 2.78.3.
355+
def patch_glib_python_codegen
356+
patch = <<~DIFF
357+
diff --git a/gio/gdbus-2.0/codegen/utils.py b/gio/gdbus-2.0/codegen/utils.py
358+
index 02046108dae49efb140c6438b03b80a73770d2c0..08f1ba9731d0582015ef9807eb739a3efa410e0d 100644
359+
--- a/gio/gdbus-2.0/codegen/utils.py
360+
+++ b/gio/gdbus-2.0/codegen/utils.py
361+
@@ -19,7 +19,7 @@
362+
#
363+
# Author: David Zeuthen <[email protected]>
364+
365+
-import distutils.version
366+
+import packaging.version
367+
import os
368+
import sys
369+
370+
@@ -166,4 +166,4 @@ def version_cmp_key(key):
371+
v = str(key[0])
372+
else:
373+
v = "0"
374+
- return (distutils.version.LooseVersion(v), key[1])
375+
+ return (packaging.version.Version(v), key[1])
376+
DIFF
377+
378+
Dir.chdir("/usr/local/Cellar/glib/2.78.3/share/glib-2.0") do
379+
_, status = Open3.capture2("patch", "-p3", stdin_data: patch)
380+
raise "Failed to execute 'patch' command" unless status.success?
381+
end
383382

384-
def bundle_uefi(_firmware_target_dir)
383+
execute "pip3", "install", "packaging"
385384
end
386385

387386
class Qemu < Host::Qemu
@@ -419,70 +418,34 @@ def brew_prefix
419418
private_constant :Qemu
420419

421420
class Xhyve
421+
attr_reader :host
422+
422423
def initialize(host)
423424
@host = host
424425
end
425426

426-
def install
427-
execute "brew", "install", "--HEAD", "xhyve"
428-
end
429-
430427
def bundle
431-
FileUtils.mkdir_p "work/bin"
432-
bundle_bhyve_uefi
433-
FileUtils.cp Bundler.which("xhyve"), "work/bin"
434-
codesign
435-
436-
xhyve_brew_path = `brew --cellar xhyve`.strip
437-
xhyve_version = `brew info xhyve --json | jq .[].installed[].version -r`.strip
438-
userboot_path = File.join(xhyve_brew_path, xhyve_version, "share/xhyve/test/userboot.so")
439-
FileUtils.cp userboot_path, "work"
440-
execute "tar", "-C", "work", "-c", "-f", "xhyve-#{host.name}.tar", "."
441-
FileUtils.rm_r "work"
428+
# Reuse previously packaged Xhyve because: "xhyve has been disabled because it does not build"
429+
# https://github.com/cross-platform-actions/resources/actions/runs/7292733675/job/19874361022#step:3:3225
430+
download_file("https://github.com/cross-platform-actions/resources/releases/download/v0.9.1/xhyve-macos.tar", "xhyve-#{host.name}.tar")
442431
end
432+
end
443433

444-
private
445-
446-
ENTITLEMENT = <<~XML
447-
<?xml version="1.0" encoding="UTF-8"?>
448-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
449-
<plist version="1.0">
450-
<dict>
451-
<key>com.apple.security.hypervisor</key>
452-
<true/>
453-
</dict>
454-
</plist>
455-
XML
456-
457-
attr_reader :host
458-
459-
def codesign
460-
Tempfile.open("entitlement") do |file|
461-
file.write ENTITLEMENT
462-
file.rewind
434+
private_constant :Xhyve
463435

464-
execute "codesign",
465-
"-s", "-",
466-
"--entitlements", file.path,
467-
"--force",
468-
"work/bin/xhyve"
469-
end
436+
class Libslirp
437+
def build
470438
end
471439

472-
def bundle_bhyve_uefi
473-
work_dir = File.join(Dir.pwd, "work")
440+
def ldflags
441+
[]
442+
end
474443

475-
Dir.mktmpdir do |dir|
476-
Dir.chdir(dir) do
477-
download_file("https://github.com/cross-platform-actions/resources/releases/download/v0.6.0/xhyve-macos.tar", "xhyve.tar")
478-
execute "tar", "xf", "xhyve.tar"
479-
FileUtils.mv "uefi.fd", work_dir
480-
end
481-
end
444+
def cleanup
482445
end
483446
end
484447

485-
private_constant :Xhyve
448+
private_constant :Libslirp
486449
end
487450

488451
class Linux < Host
@@ -494,6 +457,10 @@ def xhyve
494457
@xhyve ||= XhyveNoop.new(self)
495458
end
496459

460+
def libslirp
461+
@libslirp ||= Libslirp.new
462+
end
463+
497464
def install_prerequisite
498465
packages = %w[
499466
bash
@@ -534,6 +501,47 @@ def ldflags
534501
end
535502

536503
private_constant :Qemu
504+
505+
class Libslirp
506+
def build
507+
Dir.chdir(temp_dir) do
508+
fetch
509+
_build
510+
end
511+
end
512+
513+
def ldflags
514+
[File.join(target_path, "build", "libslirp.a")]
515+
end
516+
517+
def cleanup
518+
FileUtils.remove_entry(temp_dir)
519+
end
520+
521+
private
522+
523+
def temp_dir
524+
@temp_dir ||= Dir.mktmpdir
525+
end
526+
527+
def target_path
528+
@target_path ||= File.join(temp_dir, "libslirp-master")
529+
end
530+
531+
def fetch
532+
download_file("https://gitlab.com/qemu-project/libslirp/-/archive/master/libslirp-master.tar", "libslirp.tar")
533+
execute "tar", "-xf", "libslirp.tar"
534+
end
535+
536+
def _build
537+
Dir.chdir(target_path) do
538+
execute "meson", "setup", "-Ddefault_library=static", "build"
539+
execute "ninja", "-C", "build", "install"
540+
end
541+
end
542+
end
543+
544+
private_constant :Libslirp
537545
end
538546

539547
class XhyveNoop

test.rb

+2-3
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,14 @@ def assert_statically_linked(architecture)
5252
describe "qemu-system" do
5353
describe "x86_64" do
5454
it "contains the correct file structure for x86_64" do
55-
uefi = QemuSystemValidator.host_os == "macos" ? [] : ["uefi.fd"]
56-
5755
assert_qemu_system "x86_64", firmwares: %w[
5856
bios-256k.bin
5957
efi-e1000.rom
6058
efi-virtio.rom
6159
kvmvapic.bin
6260
vgabios-stdvga.bin
63-
].concat(uefi)
61+
uefi.fd
62+
]
6463
end
6564

6665
it "is only linked with system dependencies" do

0 commit comments

Comments
 (0)