]> git.proxmox.com Git - pve-edk2-firmware.git/blame - debian/python/UEFI/Qemu.py
bump version to 4.2023.08-4
[pve-edk2-firmware.git] / debian / python / UEFI / Qemu.py
CommitLineData
a65627a8
TL
1#
2# Copyright 2019-2021 Canonical Ltd.
3# Authors:
4# - dann frazier <dann.frazier@canonical.com>
5#
6# This program is free software: you can redistribute it and/or modify it
7# under the terms of the GNU General Public License version 3, as published
8# by the Free Software Foundation.
9#
10# This program is distributed in the hope that it will be useful, but WITHOUT
11# ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
12# SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along with
16# this program. If not, see <http://www.gnu.org/licenses/>.
17#
18
19import enum
20import os
21import shutil
22import tempfile
23
24
25class QemuEfiMachine(enum.Enum):
26 OVMF_PC = enum.auto()
27 OVMF_Q35 = enum.auto()
28 OVMF32 = enum.auto()
29 AAVMF = enum.auto()
30 AAVMF32 = enum.auto()
d7298091 31 RISCV64 = enum.auto()
a65627a8
TL
32
33
34class QemuEfiVariant(enum.Enum):
35 MS = enum.auto()
36 SECBOOT = enum.auto()
37 SNAKEOIL = enum.auto()
38
39
40class QemuEfiFlashSize(enum.Enum):
41 DEFAULT = enum.auto
42 SIZE_2MB = enum.auto()
43 SIZE_4MB = enum.auto()
44
45
46class QemuCommand:
a65627a8
TL
47 Qemu_Common_Params = [
48 '-no-user-config', '-nodefaults',
49 '-m', '256',
d7274593 50 '-smp', '1,sockets=1,cores=1,threads=1',
a65627a8
TL
51 '-display', 'none',
52 '-serial', 'stdio',
53 ]
54 Ovmf_Common_Params = Qemu_Common_Params + [
55 '-chardev', 'pty,id=charserial1',
56 '-device', 'isa-serial,chardev=charserial1,id=serial1',
57 ]
58 Aavmf_Common_Params = Qemu_Common_Params + [
59 '-machine', 'virt', '-device', 'virtio-serial-device',
60 ]
d7298091
TL
61 RiscV_Common_Params = Qemu_Common_Params + [
62 '-machine', 'virt', '-device', 'virtio-serial-device',
63 ]
a65627a8
TL
64 Machine_Base_Command = {
65 QemuEfiMachine.AAVMF: [
66 'qemu-system-aarch64', '-cpu', 'cortex-a57',
67 ] + Aavmf_Common_Params,
68 QemuEfiMachine.AAVMF32: [
69 'qemu-system-aarch64', '-cpu', 'cortex-a15',
70 ] + Aavmf_Common_Params,
71 QemuEfiMachine.OVMF_PC: [
72 'qemu-system-x86_64', '-machine', 'pc,accel=tcg',
73 ] + Ovmf_Common_Params,
74 QemuEfiMachine.OVMF_Q35: [
75 'qemu-system-x86_64', '-machine', 'q35,accel=tcg',
76 ] + Ovmf_Common_Params,
77 QemuEfiMachine.OVMF32: [
78 'qemu-system-i386', '-machine', 'q35,accel=tcg',
79 ] + Ovmf_Common_Params,
d7298091
TL
80 QemuEfiMachine.RISCV64: [
81 'qemu-system-riscv64',
82 ] + RiscV_Common_Params,
a65627a8
TL
83 }
84
85 def _get_default_flash_paths(self, machine, variant, flash_size):
86 assert(machine in QemuEfiMachine)
87 assert(variant is None or variant in QemuEfiVariant)
88 assert(flash_size in QemuEfiFlashSize)
89
90 code_ext = vars_ext = ''
91 if variant == QemuEfiVariant.MS:
92 code_ext = vars_ext = '.ms'
93 elif variant == QemuEfiVariant.SECBOOT:
94 code_ext = '.secboot'
95 elif variant == QemuEfiVariant.SNAKEOIL:
96 vars_ext = '.snakeoil'
97
98 if machine == QemuEfiMachine.AAVMF:
99 assert(flash_size == QemuEfiFlashSize.DEFAULT)
100 return (
101 f'/usr/share/AAVMF/AAVMF_CODE{code_ext}.fd',
102 f'/usr/share/AAVMF/AAVMF_VARS{code_ext}.fd',
103 )
104 if machine == QemuEfiMachine.AAVMF32:
105 assert(variant is None)
106 assert(flash_size == QemuEfiFlashSize.DEFAULT)
107 return (
108 '/usr/share/AAVMF/AAVMF32_CODE.fd',
109 '/usr/share/AAVMF/AAVMF32_VARS.fd'
110 )
111 if machine == QemuEfiMachine.OVMF32:
112 assert(variant is None or variant in [QemuEfiVariant.SECBOOT])
113 assert(
114 flash_size in [
115 QemuEfiFlashSize.DEFAULT, QemuEfiFlashSize.SIZE_4MB
116 ]
117 )
118 return (
119 '/usr/share/OVMF/OVMF32_CODE_4M.secboot.fd',
120 '/usr/share/OVMF/OVMF32_VARS_4M.fd',
121 )
122 # Remaining possibilities are OVMF variants
123 if machine == QemuEfiMachine.OVMF_PC:
124 assert(variant is None)
d7298091
TL
125 if machine == QemuEfiMachine.RISCV64:
126 assert(variant is None)
127 assert(flash_size == QemuEfiFlashSize.DEFAULT)
128 return (
129 '/usr/share/qemu-efi-riscv64/RISCV_VIRT_CODE.fd',
130 '/usr/share/qemu-efi-riscv64/RISCV_VIRT_VARS.fd',
131 )
a65627a8
TL
132 if variant == QemuEfiVariant.SNAKEOIL:
133 # We provide one size - you don't get to pick.
134 assert(flash_size == QemuEfiFlashSize.DEFAULT)
135 size_ext = '' if flash_size == QemuEfiFlashSize.SIZE_2MB else '_4M'
136 return (
137 f'/usr/share/OVMF/OVMF_CODE{size_ext}{code_ext}.fd',
138 f'/usr/share/OVMF/OVMF_VARS{size_ext}{vars_ext}.fd'
139 )
140
141 def __init__(
142 self, machine, variant=None,
143 code_path=None, vars_template_path=None,
144 flash_size=QemuEfiFlashSize.DEFAULT,
145 ):
146 assert(
147 (code_path and vars_template_path) or
148 (not code_path and not vars_template_path)
149 )
150
151 if not code_path:
152 (code_path, vars_template_path) = self._get_default_flash_paths(
153 machine, variant, flash_size)
154
155 self.pflash = self.PflashParams(code_path, vars_template_path)
156 self.command = self.Machine_Base_Command[machine] + self.pflash.params
157 if variant in [QemuEfiVariant.MS, QemuEfiVariant.SECBOOT] and \
158 flash_size == QemuEfiFlashSize.SIZE_2MB:
159 # 2MB images have 64-bit PEI that does not support S3 w/ SMM
160 self.command.extend(['-global', 'ICH9-LPC.disable_s3=1'])
161
162 def add_disk(self, path):
163 self.command = self.command + [
164 '-drive', 'file=%s,format=raw' % (path)
165 ]
166
167 def add_oem_string(self, type, string):
168 string = string.replace(",", ",,")
169 self.command = self.command + [
170 '-smbios', f'type={type},value={string}'
171 ]
172
173 class PflashParams:
174 '''
175 Used to generate the appropriate -pflash arguments for QEMU. Mostly
176 used as a fancy way to generate a per-instance vars file and have it
177 be automatically cleaned up when the object is destroyed.
178 '''
179 def __init__(self, code_path, vars_template_path):
d7298091
TL
180 self.params = [
181 '-drive',
182 'file=%s,if=pflash,format=raw,unit=0,readonly=on' %
183 (code_path),
184 ]
185 if vars_template_path is None:
186 self.varfile_path = None
187 return
a65627a8
TL
188 with tempfile.NamedTemporaryFile(delete=False) as varfile:
189 self.varfile_path = varfile.name
190 with open(vars_template_path, 'rb') as template:
191 shutil.copyfileobj(template, varfile)
d7298091
TL
192 self.params = self.params + [
193 '-drive',
194 'file=%s,if=pflash,format=raw,unit=1,readonly=off' %
195 (varfile.name)
196 ]
a65627a8
TL
197
198 def __del__(self):
d7298091
TL
199 if self.varfile_path is None:
200 return
a65627a8 201 os.unlink(self.varfile_path)