]>
Commit | Line | Data |
---|---|---|
a65627a8 TL |
1 | #!/usr/bin/env python3 |
2 | # | |
3 | # Copyright 2021 Canonical Ltd. | |
4 | # Authors: | |
5 | # - dann frazier <dann.frazier@canonical.com> | |
6 | # | |
7 | # This program is free software: you can redistribute it and/or modify it | |
8 | # under the terms of the GNU General Public License version 3, as published | |
9 | # by the Free Software Foundation. | |
10 | # | |
11 | # This program is distributed in the hope that it will be useful, but WITHOUT | |
12 | # ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | |
13 | # SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | # General Public License for more details. | |
15 | # | |
16 | # You should have received a copy of the GNU General Public License along with | |
17 | # this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | # | |
19 | ||
20 | import argparse | |
21 | import os.path | |
22 | import pexpect | |
23 | import shutil | |
24 | import sys | |
25 | from UEFI.Filesystems import FatFsImage, EfiBootableIsoImage | |
26 | from UEFI.Qemu import QemuEfiMachine, QemuEfiVariant, QemuEfiFlashSize | |
27 | from UEFI import Qemu | |
28 | ||
29 | if __name__ == '__main__': | |
30 | parser = argparse.ArgumentParser() | |
31 | parser.add_argument( | |
32 | "-f", "--flavor", help="UEFI Flavor", | |
33 | choices=['AAVMF', 'OVMF', 'OVMF_4M'], | |
34 | required=True, | |
35 | ) | |
36 | parser.add_argument( | |
37 | "-e", "--enrolldefaultkeys", | |
38 | help='Path to "EnrollDefaultKeys" EFI binary', | |
39 | required=True, | |
40 | ) | |
41 | parser.add_argument( | |
42 | "-s", "--shell", | |
43 | help='Path to "Shell" EFI binary', | |
44 | required=True, | |
45 | ) | |
46 | parser.add_argument( | |
47 | "-C", "--certificate", | |
48 | help='base64-encoded PK/KEK1 certificate', | |
49 | required=True, | |
50 | ) | |
51 | parser.add_argument( | |
52 | "-c", "--code", | |
53 | help='UEFI code image', | |
54 | required=True, | |
55 | ) | |
56 | parser.add_argument( | |
57 | "-V", "--vars-template", | |
58 | help='UEFI vars template', | |
59 | required=True, | |
60 | ) | |
61 | parser.add_argument( | |
62 | "-o", "--out-file", | |
63 | help="Output file for generated vars template", | |
64 | required=True, | |
65 | ) | |
66 | parser.add_argument("-d", "--debug", action="store_true", | |
67 | help="Emit debug messages") | |
68 | args = parser.parse_args() | |
69 | ||
70 | FlavorConfig = { | |
71 | 'AAVMF': { | |
72 | 'EfiArch': 'AA64', | |
73 | 'QemuCommand': Qemu.QemuCommand( | |
74 | QemuEfiMachine.AAVMF, | |
75 | code_path=args.code, | |
76 | vars_template_path=args.vars_template, | |
77 | ), | |
78 | }, | |
79 | 'OVMF': { | |
80 | 'EfiArch': 'X64', | |
81 | 'QemuCommand': Qemu.QemuCommand( | |
82 | QemuEfiMachine.OVMF_Q35, | |
83 | variant=QemuEfiVariant.SECBOOT, | |
84 | flash_size=QemuEfiFlashSize.SIZE_2MB, | |
85 | code_path=args.code, | |
86 | vars_template_path=args.vars_template, | |
87 | ), | |
88 | }, | |
89 | 'OVMF_4M': { | |
90 | 'EfiArch': 'X64', | |
91 | 'QemuCommand': Qemu.QemuCommand( | |
92 | QemuEfiMachine.OVMF_Q35, | |
93 | variant=QemuEfiVariant.SECBOOT, | |
94 | flash_size=QemuEfiFlashSize.SIZE_2MB, | |
95 | code_path=args.code, | |
96 | vars_template_path=args.vars_template, | |
97 | ), | |
98 | }, | |
99 | } | |
100 | ||
101 | eltorito = FatFsImage(64) | |
102 | eltorito.makedirs(os.path.join('EFI', 'BOOT')) | |
103 | removable_media_path = os.path.join( | |
104 | 'EFI', 'BOOT', f"BOOT{FlavorConfig[args.flavor]['EfiArch']}.EFI" | |
105 | ) | |
106 | eltorito.insert_file(args.shell, removable_media_path) | |
107 | eltorito.insert_file( | |
108 | args.enrolldefaultkeys, | |
109 | args.enrolldefaultkeys.split(os.path.sep)[-1] | |
110 | ) | |
111 | iso = EfiBootableIsoImage(eltorito) | |
112 | ||
113 | q = FlavorConfig[args.flavor]['QemuCommand'] | |
114 | q.add_disk(iso.path) | |
115 | q.add_oem_string(11, args.certificate) | |
116 | ||
117 | child = pexpect.spawn(' '.join(q.command)) | |
118 | if args.debug: | |
119 | child.logfile = sys.stdout.buffer | |
120 | child.expect(['Press .* or any other key to continue'], timeout=60) | |
121 | child.sendline('\x1b') | |
122 | child.expect(['Shell> ']) | |
123 | child.sendline('FS0:\r') | |
124 | child.expect(['FS0:\\\\> ']) | |
125 | child.sendline('EnrollDefaultKeys.efi\r') | |
126 | child.expect(['FS0:\\\\> ']) | |
127 | child.sendline('reset -s\r') | |
128 | child.wait() | |
129 | shutil.copy(q.pflash.varfile_path, args.out_file) |