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