]> git.proxmox.com Git - pve-edk2-firmware.git/blame_incremental - debian/python/UEFI/Qemu.py
debian: update build and packaging from Debian upstream
[pve-edk2-firmware.git] / debian / python / UEFI / Qemu.py
... / ...
CommitLineData
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()
31
32
33class QemuEfiVariant(enum.Enum):
34 MS = enum.auto()
35 SECBOOT = enum.auto()
36 SNAKEOIL = enum.auto()
37
38
39class QemuEfiFlashSize(enum.Enum):
40 DEFAULT = enum.auto
41 SIZE_2MB = enum.auto()
42 SIZE_4MB = enum.auto()
43
44
45class QemuCommand:
46 # Based on the args used by ovmf-vars-generator
47 Qemu_Common_Params = [
48 '-no-user-config', '-nodefaults',
49 '-m', '256',
50 '-smp', '2,sockets=2,cores=1,threads=1',
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 ]
61 Machine_Base_Command = {
62 QemuEfiMachine.AAVMF: [
63 'qemu-system-aarch64', '-cpu', 'cortex-a57',
64 ] + Aavmf_Common_Params,
65 QemuEfiMachine.AAVMF32: [
66 'qemu-system-aarch64', '-cpu', 'cortex-a15',
67 ] + Aavmf_Common_Params,
68 QemuEfiMachine.OVMF_PC: [
69 'qemu-system-x86_64', '-machine', 'pc,accel=tcg',
70 ] + Ovmf_Common_Params,
71 QemuEfiMachine.OVMF_Q35: [
72 'qemu-system-x86_64', '-machine', 'q35,accel=tcg',
73 ] + Ovmf_Common_Params,
74 QemuEfiMachine.OVMF32: [
75 'qemu-system-i386', '-machine', 'q35,accel=tcg',
76 ] + Ovmf_Common_Params,
77 }
78
79 def _get_default_flash_paths(self, machine, variant, flash_size):
80 assert(machine in QemuEfiMachine)
81 assert(variant is None or variant in QemuEfiVariant)
82 assert(flash_size in QemuEfiFlashSize)
83
84 code_ext = vars_ext = ''
85 if variant == QemuEfiVariant.MS:
86 code_ext = vars_ext = '.ms'
87 elif variant == QemuEfiVariant.SECBOOT:
88 code_ext = '.secboot'
89 elif variant == QemuEfiVariant.SNAKEOIL:
90 vars_ext = '.snakeoil'
91
92 if machine == QemuEfiMachine.AAVMF:
93 assert(flash_size == QemuEfiFlashSize.DEFAULT)
94 return (
95 f'/usr/share/AAVMF/AAVMF_CODE{code_ext}.fd',
96 f'/usr/share/AAVMF/AAVMF_VARS{code_ext}.fd',
97 )
98 if machine == QemuEfiMachine.AAVMF32:
99 assert(variant is None)
100 assert(flash_size == QemuEfiFlashSize.DEFAULT)
101 return (
102 '/usr/share/AAVMF/AAVMF32_CODE.fd',
103 '/usr/share/AAVMF/AAVMF32_VARS.fd'
104 )
105 if machine == QemuEfiMachine.OVMF32:
106 assert(variant is None or variant in [QemuEfiVariant.SECBOOT])
107 assert(
108 flash_size in [
109 QemuEfiFlashSize.DEFAULT, QemuEfiFlashSize.SIZE_4MB
110 ]
111 )
112 return (
113 '/usr/share/OVMF/OVMF32_CODE_4M.secboot.fd',
114 '/usr/share/OVMF/OVMF32_VARS_4M.fd',
115 )
116 # Remaining possibilities are OVMF variants
117 if machine == QemuEfiMachine.OVMF_PC:
118 assert(variant is None)
119 if variant == QemuEfiVariant.SNAKEOIL:
120 # We provide one size - you don't get to pick.
121 assert(flash_size == QemuEfiFlashSize.DEFAULT)
122 size_ext = '' if flash_size == QemuEfiFlashSize.SIZE_2MB else '_4M'
123 return (
124 f'/usr/share/OVMF/OVMF_CODE{size_ext}{code_ext}.fd',
125 f'/usr/share/OVMF/OVMF_VARS{size_ext}{vars_ext}.fd'
126 )
127
128 def __init__(
129 self, machine, variant=None,
130 code_path=None, vars_template_path=None,
131 flash_size=QemuEfiFlashSize.DEFAULT,
132 ):
133 assert(
134 (code_path and vars_template_path) or
135 (not code_path and not vars_template_path)
136 )
137
138 if not code_path:
139 (code_path, vars_template_path) = self._get_default_flash_paths(
140 machine, variant, flash_size)
141
142 self.pflash = self.PflashParams(code_path, vars_template_path)
143 self.command = self.Machine_Base_Command[machine] + self.pflash.params
144 if variant in [QemuEfiVariant.MS, QemuEfiVariant.SECBOOT] and \
145 flash_size == QemuEfiFlashSize.SIZE_2MB:
146 # 2MB images have 64-bit PEI that does not support S3 w/ SMM
147 self.command.extend(['-global', 'ICH9-LPC.disable_s3=1'])
148
149 def add_disk(self, path):
150 self.command = self.command + [
151 '-drive', 'file=%s,format=raw' % (path)
152 ]
153
154 def add_oem_string(self, type, string):
155 string = string.replace(",", ",,")
156 self.command = self.command + [
157 '-smbios', f'type={type},value={string}'
158 ]
159
160 class PflashParams:
161 '''
162 Used to generate the appropriate -pflash arguments for QEMU. Mostly
163 used as a fancy way to generate a per-instance vars file and have it
164 be automatically cleaned up when the object is destroyed.
165 '''
166 def __init__(self, code_path, vars_template_path):
167 with tempfile.NamedTemporaryFile(delete=False) as varfile:
168 self.varfile_path = varfile.name
169 with open(vars_template_path, 'rb') as template:
170 shutil.copyfileobj(template, varfile)
171 self.params = [
172 '-drive',
173 'file=%s,if=pflash,format=raw,unit=0,readonly=on' %
174 (code_path),
175 '-drive',
176 'file=%s,if=pflash,format=raw,unit=1,readonly=off' %
177 (varfile.name)
178 ]
179
180 def __del__(self):
181 os.unlink(self.varfile_path)