|
6 | 6 | "encoding/json"
|
7 | 7 | "errors"
|
8 | 8 | "fmt"
|
| 9 | + "io" |
9 | 10 | "io/fs"
|
10 | 11 | "os"
|
11 | 12 | "os/exec"
|
@@ -624,9 +625,44 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er
|
624 | 625 | return "", nil, err
|
625 | 626 | }
|
626 | 627 | logrus.Infof("Using system firmware (%q)", firmware)
|
| 628 | + if *y.Firmware.CompatUEFIViaBIOS && *y.Arch == limayaml.X8664 { |
| 629 | + firmwareVars, err := getFirmwareVars(exe, *y.Arch) |
| 630 | + if err != nil { |
| 631 | + return "", nil, err |
| 632 | + } |
| 633 | + logrus.Infof("Using system firmware vars (%q)", firmwareVars) |
| 634 | + varsFile, err := os.Open(firmwareVars) |
| 635 | + if err != nil { |
| 636 | + return "", nil, err |
| 637 | + } |
| 638 | + defer varsFile.Close() |
| 639 | + codeFile, err := os.Open(firmware) |
| 640 | + if err != nil { |
| 641 | + return "", nil, err |
| 642 | + } |
| 643 | + defer codeFile.Close() |
| 644 | + downloadedFile, err := os.OpenFile(downloadedFirmware, os.O_CREATE|os.O_WRONLY, 0o644) |
| 645 | + if err != nil { |
| 646 | + return "", nil, err |
| 647 | + } |
| 648 | + defer downloadedFile.Close() |
| 649 | + _, err = io.Copy(downloadedFile, varsFile) |
| 650 | + if err != nil { |
| 651 | + return "", nil, err |
| 652 | + } |
| 653 | + _, err = io.Copy(downloadedFile, codeFile) |
| 654 | + if err != nil { |
| 655 | + return "", nil, err |
| 656 | + } |
| 657 | + firmware = downloadedFirmware |
| 658 | + } |
627 | 659 | }
|
628 | 660 | if firmware != "" {
|
629 |
| - args = append(args, "-drive", fmt.Sprintf("if=pflash,format=raw,readonly=on,file=%s", firmware)) |
| 661 | + if *y.Firmware.CompatUEFIViaBIOS && *y.Arch == limayaml.X8664 { |
| 662 | + args = append(args, "-bios", firmware) |
| 663 | + } else { |
| 664 | + args = append(args, "-drive", fmt.Sprintf("if=pflash,format=raw,readonly=on,file=%s", firmware)) |
| 665 | + } |
630 | 666 | }
|
631 | 667 | }
|
632 | 668 |
|
@@ -1120,9 +1156,11 @@ func getFirmware(qemuExe string, arch limayaml.Arch) (string, error) {
|
1120 | 1156 | userLocalDir := filepath.Join(currentUser.HomeDir, ".local") // "$HOME/.local"
|
1121 | 1157 |
|
1122 | 1158 | relativePath := fmt.Sprintf("share/qemu/edk2-%s-code.fd", qemuEdk2Arch(arch))
|
| 1159 | + relativePathWin := fmt.Sprintf("share/edk2-%s-code.fd", qemuEdk2Arch(arch)) |
1123 | 1160 | candidates := []string{
|
1124 | 1161 | filepath.Join(userLocalDir, relativePath), // XDG-like
|
1125 | 1162 | filepath.Join(localDir, relativePath), // macOS (homebrew)
|
| 1163 | + filepath.Join(binDir, relativePathWin), // Windows installer |
1126 | 1164 | }
|
1127 | 1165 |
|
1128 | 1166 | switch arch {
|
@@ -1164,3 +1202,40 @@ func getFirmware(qemuExe string, arch limayaml.Arch) (string, error) {
|
1164 | 1202 | qemuArch := strings.TrimPrefix(filepath.Base(qemuExe), "qemu-system-")
|
1165 | 1203 | return "", fmt.Errorf("could not find firmware for %q (hint: try copying the \"edk-%s-code.fd\" firmware to $HOME/.local/share/qemu/)", arch, qemuArch)
|
1166 | 1204 | }
|
| 1205 | + |
| 1206 | +func getFirmwareVars(qemuExe string, arch limayaml.Arch) (string, error) { |
| 1207 | + var targetArch string |
| 1208 | + switch arch { |
| 1209 | + case limayaml.X8664: |
| 1210 | + targetArch = "i386" |
| 1211 | + default: |
| 1212 | + return "", fmt.Errorf("unexpected architecture: %q", arch) |
| 1213 | + } |
| 1214 | + |
| 1215 | + currentUser, err := user.Current() |
| 1216 | + if err != nil { |
| 1217 | + return "", err |
| 1218 | + } |
| 1219 | + |
| 1220 | + binDir := filepath.Dir(qemuExe) // "/usr/local/bin" |
| 1221 | + localDir := filepath.Dir(binDir) // "/usr/local" |
| 1222 | + userLocalDir := filepath.Join(currentUser.HomeDir, ".local") // "$HOME/.local" |
| 1223 | + |
| 1224 | + relativePath := fmt.Sprintf("share/qemu/edk2-%s-vars.fd", qemuEdk2Arch(targetArch)) |
| 1225 | + relativePathWin := fmt.Sprintf("share/edk2-%s-vars.fd", qemuEdk2Arch(targetArch)) |
| 1226 | + candidates := []string{ |
| 1227 | + filepath.Join(userLocalDir, relativePath), // XDG-like |
| 1228 | + filepath.Join(localDir, relativePath), // macOS (homebrew) |
| 1229 | + filepath.Join(binDir, relativePathWin), // Windows installer |
| 1230 | + } |
| 1231 | + |
| 1232 | + logrus.Debugf("firmware vars candidates = %v", candidates) |
| 1233 | + |
| 1234 | + for _, f := range candidates { |
| 1235 | + if _, err := os.Stat(f); err == nil { |
| 1236 | + return f, nil |
| 1237 | + } |
| 1238 | + } |
| 1239 | + |
| 1240 | + return "", fmt.Errorf("could not find firmware vars for %q", arch) |
| 1241 | +} |
0 commit comments