Skip to content

Commit 1cc6d9f

Browse files
committed
Add target to generate bootable ISO image
- the ISO file can be booted on UEFI only, no legaci BIOS support - USB boot is not supported (possibly will be added in future if required) Also refactor Makefile and remove incorrect dependencies on .PHONY targets. Signed-off-by: Mikhail Malyshev <[email protected]>
1 parent fa087a2 commit 1cc6d9f

File tree

2 files changed

+104
-37
lines changed

2 files changed

+104
-37
lines changed

.gitignore

+2-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ target/
55

66
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
77
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
8-
Cargo.lock
8+
# Cargo.lock
99

1010
# These are backup files generated by rustfmt
1111
**/*.rs.bk
@@ -14,7 +14,6 @@ Cargo.lock
1414
*.pdb
1515

1616
# OVMF build artifacts, logs and QEMU VM directory
17-
/ovmf-no-nvme
18-
/vm
17+
images/
1918
debug.log
2019

Makefile

+102-34
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,139 @@
11
TARGET ?= release
22

3-
OVMF_DIR = ./ovmf-no-nvme
3+
OUT_ROOT_DIR=./images
4+
5+
BOOT_ISO=$(OUT_ROOT_DIR)/efiboot.iso
6+
EFI_BOOT_IMG=$(OUT_ROOT_DIR)/efiboot.img
7+
8+
OVMF_DIR = $(OUT_ROOT_DIR)/ovmf-no-nvme
49
OVMF_FILES = \
5-
./$(OVMF_DIR)/OVMF_CODE_no_nvme.fd \
6-
./$(OVMF_DIR)/OVMF_VARS_no_nvme.fd \
7-
./$(OVMF_DIR)/OVMF_no_nvme.fd \
8-
./$(OVMF_DIR)/NvmExpressDxe.efi \
9-
./$(OVMF_DIR)/shellx64.efi
10+
$(OVMF_DIR)/OVMF_CODE_no_nvme.fd \
11+
$(OVMF_DIR)/OVMF_VARS_no_nvme.fd \
12+
$(OVMF_DIR)/OVMF_no_nvme.fd \
13+
$(OVMF_DIR)/NvmExpressDxe.efi \
14+
$(OVMF_DIR)/shellx64.efi
1015

11-
ESP_DIR = ./vm/esp
12-
NVME_DIR = ./vm/nvme
16+
ESP_DIR = $(OUT_ROOT_DIR)/esp
17+
NVME_DIR = $(OUT_ROOT_DIR)/nvme
1318

1419
BOOT_FILES = \
1520
$(ESP_DIR)/EFI/BOOT/BOOTX64.efi \
16-
$(ESP_DIR)/EFI/BOOT/JS/DRIVERS/NvmExpressDxe.efi
17-
18-
ifeq ($(TARGET),debug)
19-
BOOT_FILES += $(ESP_DIR)/EFI/BOOT/shellx64.efi
20-
endif
21+
$(ESP_DIR)/EFI/BOOT/JS/DRIVERS/NvmExpressDxe.efi \
22+
$(if $(filter debug,$(TARGET)),$(ESP_DIR)/EFI/BOOT/shellx64.efi)
2123

2224
BOOTLOADER = ./target/x86_64-unknown-uefi/$(TARGET)/jumpstart.efi
2325

2426
.PHONY: all
25-
all: run
27+
all: run-iso
2628

2729
.PHONY: ovmf
2830
ovmf: $(OVMF_FILES)
2931
$(OVMF_FILES): Dockerfile
3032
docker buildx build -o type=local,dest=$(OVMF_DIR) .
31-
# files created by the docker build may be very old
32-
# so we need to touch them to update the timestamp
33-
touch $(OVMF_FILES)
33+
# files created by the docker build may be very old
34+
# so we need to touch them to update the timestamp
35+
touch -r Dockerfile $(OVMF_FILES)
3436

35-
.PHONY: vm-dir
36-
vm-dir: $(BOOT_FILES)
37-
$(BOOT_FILES): jumpstart_$(TARGET) ovmf
37+
$(BOOT_FILES): $(BOOTLOADER) $(OVMF_FILES)
38+
@echo "Populating ESP directory"
3839
mkdir -p $(ESP_DIR)/EFI/BOOT/JS/DRIVERS
3940
mkdir -p $(NVME_DIR)
40-
touch $(NVME_DIR)/nvme-dummy.txt
41+
# touch $(NVME_DIR)/nvme-dummy.efi
4142
cp $(OVMF_DIR)/NvmExpressDxe.efi $(ESP_DIR)/EFI/BOOT/JS/DRIVERS
4243
cp $(BOOTLOADER) $(ESP_DIR)/EFI/BOOT/BOOTX64.efi
4344
# copy UEFI Shell to the ESP only for debug target
4445
ifeq ($(TARGET),debug)
4546
cp $(OVMF_DIR)/shellx64.efi $(ESP_DIR)/EFI/BOOT
4647
endif
4748

48-
.PHONY: jumpstart_debug jumpstart_release
49-
jumpstart_$(TARGET): $(BOOTLOADER)
49+
#
50+
# Gebnerate an ISO image that can be booted from UEFI only
51+
#
52+
# FIXME: should I add USB boot support?
53+
# For more information see:
54+
# https://www.0xf8.org/2020/03/recreating-isos-that-boot-from-both-dvd-and-mass-storage-such-as-usb-sticks-and-in-both-legacy-bios-and-uefi-environments/
55+
# https://wiki.debian.org/RepackBootableISO#What_to_do_if_no_file_.2F.disk.2Fmkisofs_exists
56+
# https://dev.lovelyhq.com/libburnia/libisofs/raw/branch/master/doc/boot_sectors.txt
57+
# https://fedoraproject.org/wiki/User:Pjones/BootableCDsForBIOSAndUEFI#New_UEFI.2FBIOS_hybrid_method
58+
.PHONY: iso
59+
iso: $(BOOT_ISO)
60+
$(BOOT_ISO): $(EFI_BOOT_IMG)
61+
# create a temorray directory
62+
$(eval iso_tmp_dir:=$(shell mktemp -d))
63+
cp -r $(ESP_DIR)/* $(iso_tmp_dir)
64+
cp $^ $(iso_tmp_dir)/EFI/BOOT/efiboot.img
65+
@mkisofs \
66+
-o $@ \
67+
-R -J -v -d -N \
68+
-x $@ \
69+
-hide-rr-moved \
70+
-no-emul-boot \
71+
-eltorito-platform efi \
72+
-eltorito-boot EFI/BOOT/efiboot.img \
73+
-V "EFIBOOTISO" \
74+
-A "EFI Boot ISO Test" \
75+
$(iso_tmp_dir)
76+
# cleanup
77+
rm -rf $(iso_tmp_dir)
78+
79+
$(EFI_BOOT_IMG): $(BOOT_FILES)
80+
# Create a FAT32 image for the UEFI boot files
81+
# remove image file if it already exists so we do not calculate its size
82+
rm -f $@
83+
# calculate the size of the image in megabytes
84+
# $(eval image_size:=$(shell du -sm $(ESP_DIR) | cut -f1))
85+
86+
@echo "Creating FAT32 image with size $(image_size)"
87+
88+
dd if=/dev/zero of=$@ bs=1M count=$(image_size)
89+
mkfs.vfat -n 'JSEFIBOOT' $@
90+
91+
mmd -i $@ ::EFI
92+
mmd -i $@ ::EFI/BOOT
93+
mmd -i $@ ::EFI/BOOT/JS
94+
mmd -i $@ ::EFI/BOOT/JS/DRIVERS
5095

51-
jumpstart_debug: CARGO_TARGET:=
52-
jumpstart_release: CARGO_TARGET:=--release
96+
mcopy -i $@ $(ESP_DIR)/EFI/BOOT/BOOTX64.efi ::EFI/BOOT/BOOTX64.EFI
97+
mcopy -i $@ $(ESP_DIR)/EFI/BOOT/JS/DRIVERS/NvmExpressDxe.efi ::EFI/BOOT/JS/DRIVERS/NvmExpressDxe.efi
98+
ifeq ($(TARGET),debug)
99+
mcopy -i $@ $(ESP_DIR)/EFI/BOOT/shellx64.efi ::EFI/BOOT/SHELLX64.EFI
100+
endif
101+
102+
RUST_SRC_FILES := $(shell find ./src -type f -name '*.rs')
103+
RUST_SRC_FILES += Cargo.toml Cargo.lock rust-toolchain.toml
104+
105+
$(BOOTLOADER): $(RUST_SRC_FILES)
106+
cargo build --target=x86_64-unknown-uefi $(if $(filter release,$(TARGET)),--release)
107+
108+
$(OUT_ROOT_DIR)/nvme-1.img:
109+
dd if=/dev/zero of=$@ bs=1M count=1024
110+
111+
.PHONY: run-iso
112+
run-iso: ovmf $(BOOT_ISO)
113+
qemu-system-x86_64 -enable-kvm -serial stdio \
114+
-debugcon file:debug.log -global isa-debugcon.iobase=0x402 \
115+
-bios $(OVMF_DIR)/OVMF_no_nvme.fd \
116+
-cdrom $(BOOT_ISO) -boot d -m 512
53117

54-
$(BOOTLOADER): src/*.rs
55-
cargo build --target=x86_64-unknown-uefi $(CARGO_TARGET)
118+
.PHONY: check-iso
119+
check-iso: $(BOOT_ISO)
120+
xorriso -indev $^ -report_system_area plain -report_el_torito plain
56121

57122
.PHONY: run
58-
run: vm-dir
123+
run: $(OUT_ROOT_DIR)/nvme-1.img $(BOOT_FILES)
59124
qemu-system-x86_64 -enable-kvm -serial stdio \
60125
-debugcon file:debug.log -global isa-debugcon.iobase=0x402 \
61-
-drive if=pflash,format=raw,unit=0,file=./$(OVMF_DIR)/OVMF_CODE_no_nvme.fd,readonly=on \
62-
-drive if=pflash,format=raw,unit=1,file=./$(OVMF_DIR)/OVMF_VARS_no_nvme.fd \
126+
-drive if=pflash,format=raw,unit=0,file=$(OVMF_DIR)/OVMF_CODE_no_nvme.fd,readonly=on \
127+
-drive if=pflash,format=raw,unit=1,file=$(OVMF_DIR)/OVMF_VARS_no_nvme.fd \
63128
-drive format=raw,file=fat:rw:$(NVME_DIR),if=none,id=nvm \
64129
-device nvme,serial=deadbeef,drive=nvm \
65-
-drive format=raw,file=fat:rw:$(ESP_DIR)
130+
-drive format=raw,file=$<,if=none,id=nvm-1 \
131+
-device nvme,serial=beefdead,drive=nvm-1 \
132+
-drive format=raw,file=fat:rw:$(ESP_DIR)
66133

67134
.PHONY: clean
68135
clean:
69-
rm -rf $(OVMF_DIR)
70-
rm -rf ./vm
71-
rm debug.log
136+
cargo clean
137+
rm -rf $(OUT_ROOT_DIR)
138+
rm -f debug.log
139+
rm -f efiboot.iso

0 commit comments

Comments
 (0)