1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2019 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker use std::mem;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::result;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::slice;
8*bb4ee6a4SAndroid Build Coastguard Worker
9*bb4ee6a4SAndroid Build Coastguard Worker use arch::SmbiosOptions;
10*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
11*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error;
12*bb4ee6a4SAndroid Build Coastguard Worker use uuid::Uuid;
13*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
14*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
15*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
16*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromBytes;
17*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromZeroes;
18*bb4ee6a4SAndroid Build Coastguard Worker
19*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
20*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
21*bb4ee6a4SAndroid Build Coastguard Worker pub enum Error {
22*bb4ee6a4SAndroid Build Coastguard Worker /// The SMBIOS table has too little address space to be stored.
23*bb4ee6a4SAndroid Build Coastguard Worker #[error("The SMBIOS table has too little address space to be stored")]
24*bb4ee6a4SAndroid Build Coastguard Worker AddressOverflow,
25*bb4ee6a4SAndroid Build Coastguard Worker /// Failure while zeroing out the memory for the SMBIOS table.
26*bb4ee6a4SAndroid Build Coastguard Worker #[error("Failure while zeroing out the memory for the SMBIOS table")]
27*bb4ee6a4SAndroid Build Coastguard Worker Clear,
28*bb4ee6a4SAndroid Build Coastguard Worker /// Invalid table entry point checksum
29*bb4ee6a4SAndroid Build Coastguard Worker #[error("Failure to verify host SMBIOS entry checksum")]
30*bb4ee6a4SAndroid Build Coastguard Worker InvalidChecksum,
31*bb4ee6a4SAndroid Build Coastguard Worker /// Incorrect or not readable host SMBIOS data
32*bb4ee6a4SAndroid Build Coastguard Worker #[error("Failure to read host SMBIOS data")]
33*bb4ee6a4SAndroid Build Coastguard Worker InvalidInput,
34*bb4ee6a4SAndroid Build Coastguard Worker /// Failure while reading SMBIOS data file
35*bb4ee6a4SAndroid Build Coastguard Worker #[error("Failure while reading SMBIOS data file")]
36*bb4ee6a4SAndroid Build Coastguard Worker IoFailed,
37*bb4ee6a4SAndroid Build Coastguard Worker /// There was too little guest memory to store the entire SMBIOS table.
38*bb4ee6a4SAndroid Build Coastguard Worker #[error("There was too little guest memory to store the SMBIOS table")]
39*bb4ee6a4SAndroid Build Coastguard Worker NotEnoughMemory,
40*bb4ee6a4SAndroid Build Coastguard Worker /// A provided string contained a null character
41*bb4ee6a4SAndroid Build Coastguard Worker #[error("a provided SMBIOS string contains a null character")]
42*bb4ee6a4SAndroid Build Coastguard Worker StringHasNullCharacter,
43*bb4ee6a4SAndroid Build Coastguard Worker /// Too many OEM strings provided
44*bb4ee6a4SAndroid Build Coastguard Worker #[error("Too many OEM strings were provided, limited to 255")]
45*bb4ee6a4SAndroid Build Coastguard Worker TooManyOemStrings,
46*bb4ee6a4SAndroid Build Coastguard Worker /// Failure to write additional data to memory
47*bb4ee6a4SAndroid Build Coastguard Worker #[error("Failure to write additional data to memory")]
48*bb4ee6a4SAndroid Build Coastguard Worker WriteData,
49*bb4ee6a4SAndroid Build Coastguard Worker /// Failure to write SMBIOS entrypoint structure
50*bb4ee6a4SAndroid Build Coastguard Worker #[error("Failure to write SMBIOS entrypoint structure")]
51*bb4ee6a4SAndroid Build Coastguard Worker WriteSmbiosEp,
52*bb4ee6a4SAndroid Build Coastguard Worker }
53*bb4ee6a4SAndroid Build Coastguard Worker
54*bb4ee6a4SAndroid Build Coastguard Worker pub type Result<T> = result::Result<T, Error>;
55*bb4ee6a4SAndroid Build Coastguard Worker
56*bb4ee6a4SAndroid Build Coastguard Worker const SMBIOS_START: u64 = 0xf0000; // First possible location per the spec.
57*bb4ee6a4SAndroid Build Coastguard Worker
58*bb4ee6a4SAndroid Build Coastguard Worker // Constants sourced from SMBIOS Spec 3.2.0.
59*bb4ee6a4SAndroid Build Coastguard Worker const SM3_MAGIC_IDENT: &[u8; 5usize] = b"_SM3_";
60*bb4ee6a4SAndroid Build Coastguard Worker const BIOS_INFORMATION: u8 = 0;
61*bb4ee6a4SAndroid Build Coastguard Worker const SYSTEM_INFORMATION: u8 = 1;
62*bb4ee6a4SAndroid Build Coastguard Worker const OEM_STRING: u8 = 11;
63*bb4ee6a4SAndroid Build Coastguard Worker const END_OF_TABLE: u8 = 127;
64*bb4ee6a4SAndroid Build Coastguard Worker const PCI_SUPPORTED: u64 = 1 << 7;
65*bb4ee6a4SAndroid Build Coastguard Worker const IS_VIRTUAL_MACHINE: u8 = 1 << 4;
66*bb4ee6a4SAndroid Build Coastguard Worker
67*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_SMBIOS_BIOS_VENDOR: &str = "crosvm";
68*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_SMBIOS_BIOS_VERSION: &str = "0";
69*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_SMBIOS_MANUFACTURER: &str = "ChromiumOS";
70*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_SMBIOS_PRODUCT_NAME: &str = "crosvm";
71*bb4ee6a4SAndroid Build Coastguard Worker
compute_checksum<T: Copy>(v: &T) -> u872*bb4ee6a4SAndroid Build Coastguard Worker fn compute_checksum<T: Copy>(v: &T) -> u8 {
73*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
74*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we are only reading the bytes within the size of the `T` reference `v`.
75*bb4ee6a4SAndroid Build Coastguard Worker let v_slice = unsafe { slice::from_raw_parts(v as *const T as *const u8, mem::size_of::<T>()) };
76*bb4ee6a4SAndroid Build Coastguard Worker let mut checksum: u8 = 0;
77*bb4ee6a4SAndroid Build Coastguard Worker for i in v_slice.iter() {
78*bb4ee6a4SAndroid Build Coastguard Worker checksum = checksum.wrapping_add(*i);
79*bb4ee6a4SAndroid Build Coastguard Worker }
80*bb4ee6a4SAndroid Build Coastguard Worker (!checksum).wrapping_add(1)
81*bb4ee6a4SAndroid Build Coastguard Worker }
82*bb4ee6a4SAndroid Build Coastguard Worker
83*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, packed)]
84*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default, Clone, Copy, FromZeroes, FromBytes, AsBytes)]
85*bb4ee6a4SAndroid Build Coastguard Worker pub struct Smbios23Intermediate {
86*bb4ee6a4SAndroid Build Coastguard Worker pub signature: [u8; 5usize],
87*bb4ee6a4SAndroid Build Coastguard Worker pub checksum: u8,
88*bb4ee6a4SAndroid Build Coastguard Worker pub length: u16,
89*bb4ee6a4SAndroid Build Coastguard Worker pub address: u32,
90*bb4ee6a4SAndroid Build Coastguard Worker pub count: u16,
91*bb4ee6a4SAndroid Build Coastguard Worker pub revision: u8,
92*bb4ee6a4SAndroid Build Coastguard Worker }
93*bb4ee6a4SAndroid Build Coastguard Worker
94*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, packed)]
95*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default, Clone, Copy, FromZeroes, FromBytes, AsBytes)]
96*bb4ee6a4SAndroid Build Coastguard Worker pub struct Smbios23Entrypoint {
97*bb4ee6a4SAndroid Build Coastguard Worker pub signature: [u8; 4usize],
98*bb4ee6a4SAndroid Build Coastguard Worker pub checksum: u8,
99*bb4ee6a4SAndroid Build Coastguard Worker pub length: u8,
100*bb4ee6a4SAndroid Build Coastguard Worker pub majorver: u8,
101*bb4ee6a4SAndroid Build Coastguard Worker pub minorver: u8,
102*bb4ee6a4SAndroid Build Coastguard Worker pub max_size: u16,
103*bb4ee6a4SAndroid Build Coastguard Worker pub revision: u8,
104*bb4ee6a4SAndroid Build Coastguard Worker pub reserved: [u8; 5usize],
105*bb4ee6a4SAndroid Build Coastguard Worker pub dmi: Smbios23Intermediate,
106*bb4ee6a4SAndroid Build Coastguard Worker }
107*bb4ee6a4SAndroid Build Coastguard Worker
108*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, packed)]
109*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default, Clone, Copy, FromZeroes, FromBytes, AsBytes)]
110*bb4ee6a4SAndroid Build Coastguard Worker pub struct Smbios30Entrypoint {
111*bb4ee6a4SAndroid Build Coastguard Worker pub signature: [u8; 5usize],
112*bb4ee6a4SAndroid Build Coastguard Worker pub checksum: u8,
113*bb4ee6a4SAndroid Build Coastguard Worker pub length: u8,
114*bb4ee6a4SAndroid Build Coastguard Worker pub majorver: u8,
115*bb4ee6a4SAndroid Build Coastguard Worker pub minorver: u8,
116*bb4ee6a4SAndroid Build Coastguard Worker pub docrev: u8,
117*bb4ee6a4SAndroid Build Coastguard Worker pub revision: u8,
118*bb4ee6a4SAndroid Build Coastguard Worker pub reserved: u8,
119*bb4ee6a4SAndroid Build Coastguard Worker pub max_size: u32,
120*bb4ee6a4SAndroid Build Coastguard Worker pub physptr: u64,
121*bb4ee6a4SAndroid Build Coastguard Worker }
122*bb4ee6a4SAndroid Build Coastguard Worker
123*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, packed)]
124*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default, Clone, Copy, FromZeroes, FromBytes, AsBytes)]
125*bb4ee6a4SAndroid Build Coastguard Worker pub struct SmbiosBiosInfo {
126*bb4ee6a4SAndroid Build Coastguard Worker pub typ: u8,
127*bb4ee6a4SAndroid Build Coastguard Worker pub length: u8,
128*bb4ee6a4SAndroid Build Coastguard Worker pub handle: u16,
129*bb4ee6a4SAndroid Build Coastguard Worker pub vendor: u8,
130*bb4ee6a4SAndroid Build Coastguard Worker pub version: u8,
131*bb4ee6a4SAndroid Build Coastguard Worker pub start_addr: u16,
132*bb4ee6a4SAndroid Build Coastguard Worker pub release_date: u8,
133*bb4ee6a4SAndroid Build Coastguard Worker pub rom_size: u8,
134*bb4ee6a4SAndroid Build Coastguard Worker pub characteristics: u64,
135*bb4ee6a4SAndroid Build Coastguard Worker pub characteristics_ext1: u8,
136*bb4ee6a4SAndroid Build Coastguard Worker pub characteristics_ext2: u8,
137*bb4ee6a4SAndroid Build Coastguard Worker }
138*bb4ee6a4SAndroid Build Coastguard Worker
139*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, packed)]
140*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default, Clone, Copy, FromZeroes, FromBytes, AsBytes)]
141*bb4ee6a4SAndroid Build Coastguard Worker pub struct SmbiosSysInfo {
142*bb4ee6a4SAndroid Build Coastguard Worker pub typ: u8,
143*bb4ee6a4SAndroid Build Coastguard Worker pub length: u8,
144*bb4ee6a4SAndroid Build Coastguard Worker pub handle: u16,
145*bb4ee6a4SAndroid Build Coastguard Worker pub manufacturer: u8,
146*bb4ee6a4SAndroid Build Coastguard Worker pub product_name: u8,
147*bb4ee6a4SAndroid Build Coastguard Worker pub version: u8,
148*bb4ee6a4SAndroid Build Coastguard Worker pub serial_number: u8,
149*bb4ee6a4SAndroid Build Coastguard Worker pub uuid: [u8; 16usize],
150*bb4ee6a4SAndroid Build Coastguard Worker pub wake_up_type: u8,
151*bb4ee6a4SAndroid Build Coastguard Worker pub sku: u8,
152*bb4ee6a4SAndroid Build Coastguard Worker pub family: u8,
153*bb4ee6a4SAndroid Build Coastguard Worker }
154*bb4ee6a4SAndroid Build Coastguard Worker
155*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, packed)]
156*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default, Clone, Copy, FromZeroes, FromBytes, AsBytes)]
157*bb4ee6a4SAndroid Build Coastguard Worker pub struct SmbiosOemStrings {
158*bb4ee6a4SAndroid Build Coastguard Worker pub typ: u8,
159*bb4ee6a4SAndroid Build Coastguard Worker pub length: u8,
160*bb4ee6a4SAndroid Build Coastguard Worker pub handle: u16,
161*bb4ee6a4SAndroid Build Coastguard Worker pub count: u8,
162*bb4ee6a4SAndroid Build Coastguard Worker }
163*bb4ee6a4SAndroid Build Coastguard Worker
164*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, packed)]
165*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default, Clone, Copy, FromZeroes, FromBytes, AsBytes)]
166*bb4ee6a4SAndroid Build Coastguard Worker pub struct SmbiosEndOfTable {
167*bb4ee6a4SAndroid Build Coastguard Worker pub typ: u8,
168*bb4ee6a4SAndroid Build Coastguard Worker pub length: u8,
169*bb4ee6a4SAndroid Build Coastguard Worker pub handle: u16,
170*bb4ee6a4SAndroid Build Coastguard Worker }
171*bb4ee6a4SAndroid Build Coastguard Worker
write_and_incr<T: AsBytes + FromBytes>( mem: &GuestMemory, val: T, mut curptr: GuestAddress, ) -> Result<GuestAddress>172*bb4ee6a4SAndroid Build Coastguard Worker fn write_and_incr<T: AsBytes + FromBytes>(
173*bb4ee6a4SAndroid Build Coastguard Worker mem: &GuestMemory,
174*bb4ee6a4SAndroid Build Coastguard Worker val: T,
175*bb4ee6a4SAndroid Build Coastguard Worker mut curptr: GuestAddress,
176*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<GuestAddress> {
177*bb4ee6a4SAndroid Build Coastguard Worker mem.write_obj_at_addr(val, curptr)
178*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| Error::WriteData)?;
179*bb4ee6a4SAndroid Build Coastguard Worker curptr = curptr
180*bb4ee6a4SAndroid Build Coastguard Worker .checked_add(mem::size_of::<T>() as u64)
181*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(Error::NotEnoughMemory)?;
182*bb4ee6a4SAndroid Build Coastguard Worker Ok(curptr)
183*bb4ee6a4SAndroid Build Coastguard Worker }
184*bb4ee6a4SAndroid Build Coastguard Worker
write_string(mem: &GuestMemory, val: &str, mut curptr: GuestAddress) -> Result<GuestAddress>185*bb4ee6a4SAndroid Build Coastguard Worker fn write_string(mem: &GuestMemory, val: &str, mut curptr: GuestAddress) -> Result<GuestAddress> {
186*bb4ee6a4SAndroid Build Coastguard Worker for c in val.as_bytes().iter() {
187*bb4ee6a4SAndroid Build Coastguard Worker if *c == 0 {
188*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::StringHasNullCharacter);
189*bb4ee6a4SAndroid Build Coastguard Worker }
190*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_and_incr(mem, *c, curptr)?;
191*bb4ee6a4SAndroid Build Coastguard Worker }
192*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_and_incr(mem, 0_u8, curptr)?;
193*bb4ee6a4SAndroid Build Coastguard Worker Ok(curptr)
194*bb4ee6a4SAndroid Build Coastguard Worker }
195*bb4ee6a4SAndroid Build Coastguard Worker
setup_smbios(mem: &GuestMemory, options: &SmbiosOptions, bios_size: u64) -> Result<()>196*bb4ee6a4SAndroid Build Coastguard Worker pub fn setup_smbios(mem: &GuestMemory, options: &SmbiosOptions, bios_size: u64) -> Result<()> {
197*bb4ee6a4SAndroid Build Coastguard Worker let physptr = GuestAddress(SMBIOS_START)
198*bb4ee6a4SAndroid Build Coastguard Worker .checked_add(mem::size_of::<Smbios30Entrypoint>() as u64)
199*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(Error::NotEnoughMemory)?;
200*bb4ee6a4SAndroid Build Coastguard Worker let mut curptr = physptr;
201*bb4ee6a4SAndroid Build Coastguard Worker let mut handle = 0;
202*bb4ee6a4SAndroid Build Coastguard Worker
203*bb4ee6a4SAndroid Build Coastguard Worker {
204*bb4ee6a4SAndroid Build Coastguard Worker handle += 1;
205*bb4ee6a4SAndroid Build Coastguard Worker
206*bb4ee6a4SAndroid Build Coastguard Worker // BIOS ROM size is encoded as 64K * (n + 1)
207*bb4ee6a4SAndroid Build Coastguard Worker let rom_size = (bios_size >> 16)
208*bb4ee6a4SAndroid Build Coastguard Worker .saturating_sub(1)
209*bb4ee6a4SAndroid Build Coastguard Worker .try_into()
210*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or(0xFF);
211*bb4ee6a4SAndroid Build Coastguard Worker
212*bb4ee6a4SAndroid Build Coastguard Worker let smbios_biosinfo = SmbiosBiosInfo {
213*bb4ee6a4SAndroid Build Coastguard Worker typ: BIOS_INFORMATION,
214*bb4ee6a4SAndroid Build Coastguard Worker length: mem::size_of::<SmbiosBiosInfo>() as u8,
215*bb4ee6a4SAndroid Build Coastguard Worker handle,
216*bb4ee6a4SAndroid Build Coastguard Worker vendor: 1, // First string written in this section
217*bb4ee6a4SAndroid Build Coastguard Worker version: 2, // Second string written in this section
218*bb4ee6a4SAndroid Build Coastguard Worker characteristics: PCI_SUPPORTED,
219*bb4ee6a4SAndroid Build Coastguard Worker characteristics_ext2: IS_VIRTUAL_MACHINE,
220*bb4ee6a4SAndroid Build Coastguard Worker rom_size,
221*bb4ee6a4SAndroid Build Coastguard Worker ..Default::default()
222*bb4ee6a4SAndroid Build Coastguard Worker };
223*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_and_incr(mem, smbios_biosinfo, curptr)?;
224*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_string(
225*bb4ee6a4SAndroid Build Coastguard Worker mem,
226*bb4ee6a4SAndroid Build Coastguard Worker options
227*bb4ee6a4SAndroid Build Coastguard Worker .bios_vendor
228*bb4ee6a4SAndroid Build Coastguard Worker .as_deref()
229*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or(DEFAULT_SMBIOS_BIOS_VENDOR),
230*bb4ee6a4SAndroid Build Coastguard Worker curptr,
231*bb4ee6a4SAndroid Build Coastguard Worker )?;
232*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_string(
233*bb4ee6a4SAndroid Build Coastguard Worker mem,
234*bb4ee6a4SAndroid Build Coastguard Worker options
235*bb4ee6a4SAndroid Build Coastguard Worker .bios_version
236*bb4ee6a4SAndroid Build Coastguard Worker .as_deref()
237*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or(DEFAULT_SMBIOS_BIOS_VERSION),
238*bb4ee6a4SAndroid Build Coastguard Worker curptr,
239*bb4ee6a4SAndroid Build Coastguard Worker )?;
240*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_and_incr(mem, 0_u8, curptr)?;
241*bb4ee6a4SAndroid Build Coastguard Worker }
242*bb4ee6a4SAndroid Build Coastguard Worker
243*bb4ee6a4SAndroid Build Coastguard Worker {
244*bb4ee6a4SAndroid Build Coastguard Worker handle += 1;
245*bb4ee6a4SAndroid Build Coastguard Worker let smbios_sysinfo = SmbiosSysInfo {
246*bb4ee6a4SAndroid Build Coastguard Worker typ: SYSTEM_INFORMATION,
247*bb4ee6a4SAndroid Build Coastguard Worker length: mem::size_of::<SmbiosSysInfo>() as u8,
248*bb4ee6a4SAndroid Build Coastguard Worker handle,
249*bb4ee6a4SAndroid Build Coastguard Worker // PC vendors consistently use little-endian ordering for reasons
250*bb4ee6a4SAndroid Build Coastguard Worker uuid: options.uuid.unwrap_or(Uuid::nil()).to_bytes_le(),
251*bb4ee6a4SAndroid Build Coastguard Worker manufacturer: 1, // First string written in this section
252*bb4ee6a4SAndroid Build Coastguard Worker product_name: 2, // Second string written in this section
253*bb4ee6a4SAndroid Build Coastguard Worker serial_number: if options.serial_number.is_some() {
254*bb4ee6a4SAndroid Build Coastguard Worker 3 // Third string written in this section
255*bb4ee6a4SAndroid Build Coastguard Worker } else {
256*bb4ee6a4SAndroid Build Coastguard Worker 0 // Serial number not specified
257*bb4ee6a4SAndroid Build Coastguard Worker },
258*bb4ee6a4SAndroid Build Coastguard Worker ..Default::default()
259*bb4ee6a4SAndroid Build Coastguard Worker };
260*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_and_incr(mem, smbios_sysinfo, curptr)?;
261*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_string(
262*bb4ee6a4SAndroid Build Coastguard Worker mem,
263*bb4ee6a4SAndroid Build Coastguard Worker options
264*bb4ee6a4SAndroid Build Coastguard Worker .manufacturer
265*bb4ee6a4SAndroid Build Coastguard Worker .as_deref()
266*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or(DEFAULT_SMBIOS_MANUFACTURER),
267*bb4ee6a4SAndroid Build Coastguard Worker curptr,
268*bb4ee6a4SAndroid Build Coastguard Worker )?;
269*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_string(
270*bb4ee6a4SAndroid Build Coastguard Worker mem,
271*bb4ee6a4SAndroid Build Coastguard Worker options
272*bb4ee6a4SAndroid Build Coastguard Worker .product_name
273*bb4ee6a4SAndroid Build Coastguard Worker .as_deref()
274*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or(DEFAULT_SMBIOS_PRODUCT_NAME),
275*bb4ee6a4SAndroid Build Coastguard Worker curptr,
276*bb4ee6a4SAndroid Build Coastguard Worker )?;
277*bb4ee6a4SAndroid Build Coastguard Worker if let Some(serial_number) = options.serial_number.as_deref() {
278*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_string(mem, serial_number, curptr)?;
279*bb4ee6a4SAndroid Build Coastguard Worker }
280*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_and_incr(mem, 0u8, curptr)?;
281*bb4ee6a4SAndroid Build Coastguard Worker }
282*bb4ee6a4SAndroid Build Coastguard Worker
283*bb4ee6a4SAndroid Build Coastguard Worker if !options.oem_strings.is_empty() {
284*bb4ee6a4SAndroid Build Coastguard Worker // AFAIK nothing prevents us from creating multiple OEM string tables
285*bb4ee6a4SAndroid Build Coastguard Worker // if we have more than 255 strings, but 255 already seems pretty
286*bb4ee6a4SAndroid Build Coastguard Worker // excessive.
287*bb4ee6a4SAndroid Build Coastguard Worker if options.oem_strings.len() > u8::MAX.into() {
288*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::TooManyOemStrings);
289*bb4ee6a4SAndroid Build Coastguard Worker }
290*bb4ee6a4SAndroid Build Coastguard Worker handle += 1;
291*bb4ee6a4SAndroid Build Coastguard Worker let smbios_oemstring = SmbiosOemStrings {
292*bb4ee6a4SAndroid Build Coastguard Worker typ: OEM_STRING,
293*bb4ee6a4SAndroid Build Coastguard Worker length: mem::size_of::<SmbiosOemStrings>() as u8,
294*bb4ee6a4SAndroid Build Coastguard Worker handle,
295*bb4ee6a4SAndroid Build Coastguard Worker count: options.oem_strings.len() as u8,
296*bb4ee6a4SAndroid Build Coastguard Worker };
297*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_and_incr(mem, smbios_oemstring, curptr)?;
298*bb4ee6a4SAndroid Build Coastguard Worker for oem_string in &options.oem_strings {
299*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_string(mem, oem_string, curptr)?;
300*bb4ee6a4SAndroid Build Coastguard Worker }
301*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_and_incr(mem, 0u8, curptr)?;
302*bb4ee6a4SAndroid Build Coastguard Worker }
303*bb4ee6a4SAndroid Build Coastguard Worker
304*bb4ee6a4SAndroid Build Coastguard Worker {
305*bb4ee6a4SAndroid Build Coastguard Worker handle += 1;
306*bb4ee6a4SAndroid Build Coastguard Worker let smbios_sysinfo = SmbiosEndOfTable {
307*bb4ee6a4SAndroid Build Coastguard Worker typ: END_OF_TABLE,
308*bb4ee6a4SAndroid Build Coastguard Worker length: mem::size_of::<SmbiosEndOfTable>() as u8,
309*bb4ee6a4SAndroid Build Coastguard Worker handle,
310*bb4ee6a4SAndroid Build Coastguard Worker };
311*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_and_incr(mem, smbios_sysinfo, curptr)?;
312*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_and_incr(mem, 0_u8, curptr)?; // No strings
313*bb4ee6a4SAndroid Build Coastguard Worker curptr = write_and_incr(mem, 0_u8, curptr)?; // Structure terminator
314*bb4ee6a4SAndroid Build Coastguard Worker }
315*bb4ee6a4SAndroid Build Coastguard Worker
316*bb4ee6a4SAndroid Build Coastguard Worker {
317*bb4ee6a4SAndroid Build Coastguard Worker let mut smbios_ep = Smbios30Entrypoint::default();
318*bb4ee6a4SAndroid Build Coastguard Worker smbios_ep.signature = *SM3_MAGIC_IDENT;
319*bb4ee6a4SAndroid Build Coastguard Worker smbios_ep.length = mem::size_of::<Smbios30Entrypoint>() as u8;
320*bb4ee6a4SAndroid Build Coastguard Worker // SMBIOS rev 3.2.0
321*bb4ee6a4SAndroid Build Coastguard Worker smbios_ep.majorver = 0x03;
322*bb4ee6a4SAndroid Build Coastguard Worker smbios_ep.minorver = 0x02;
323*bb4ee6a4SAndroid Build Coastguard Worker smbios_ep.docrev = 0x00;
324*bb4ee6a4SAndroid Build Coastguard Worker smbios_ep.revision = 0x01; // SMBIOS 3.0
325*bb4ee6a4SAndroid Build Coastguard Worker smbios_ep.max_size = curptr.offset_from(physptr) as u32;
326*bb4ee6a4SAndroid Build Coastguard Worker smbios_ep.physptr = physptr.offset();
327*bb4ee6a4SAndroid Build Coastguard Worker smbios_ep.checksum = compute_checksum(&smbios_ep);
328*bb4ee6a4SAndroid Build Coastguard Worker mem.write_obj_at_addr(smbios_ep, GuestAddress(SMBIOS_START))
329*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| Error::WriteSmbiosEp)?;
330*bb4ee6a4SAndroid Build Coastguard Worker }
331*bb4ee6a4SAndroid Build Coastguard Worker
332*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
333*bb4ee6a4SAndroid Build Coastguard Worker }
334*bb4ee6a4SAndroid Build Coastguard Worker
335*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
336*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
337*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
338*bb4ee6a4SAndroid Build Coastguard Worker
339*bb4ee6a4SAndroid Build Coastguard Worker #[test]
struct_size()340*bb4ee6a4SAndroid Build Coastguard Worker fn struct_size() {
341*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
342*bb4ee6a4SAndroid Build Coastguard Worker mem::size_of::<Smbios23Entrypoint>(),
343*bb4ee6a4SAndroid Build Coastguard Worker 0x1fusize,
344*bb4ee6a4SAndroid Build Coastguard Worker concat!("Size of: ", stringify!(Smbios23Entrypoint))
345*bb4ee6a4SAndroid Build Coastguard Worker );
346*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
347*bb4ee6a4SAndroid Build Coastguard Worker mem::size_of::<Smbios30Entrypoint>(),
348*bb4ee6a4SAndroid Build Coastguard Worker 0x18usize,
349*bb4ee6a4SAndroid Build Coastguard Worker concat!("Size of: ", stringify!(Smbios30Entrypoint))
350*bb4ee6a4SAndroid Build Coastguard Worker );
351*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
352*bb4ee6a4SAndroid Build Coastguard Worker mem::size_of::<SmbiosBiosInfo>(),
353*bb4ee6a4SAndroid Build Coastguard Worker 0x14usize,
354*bb4ee6a4SAndroid Build Coastguard Worker concat!("Size of: ", stringify!(SmbiosBiosInfo))
355*bb4ee6a4SAndroid Build Coastguard Worker );
356*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
357*bb4ee6a4SAndroid Build Coastguard Worker mem::size_of::<SmbiosSysInfo>(),
358*bb4ee6a4SAndroid Build Coastguard Worker 0x1busize,
359*bb4ee6a4SAndroid Build Coastguard Worker concat!("Size of: ", stringify!(SmbiosSysInfo))
360*bb4ee6a4SAndroid Build Coastguard Worker );
361*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
362*bb4ee6a4SAndroid Build Coastguard Worker mem::size_of::<SmbiosOemStrings>(),
363*bb4ee6a4SAndroid Build Coastguard Worker 0x5usize,
364*bb4ee6a4SAndroid Build Coastguard Worker concat!("Size of: ", stringify!(SmbiosOemStrings))
365*bb4ee6a4SAndroid Build Coastguard Worker );
366*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
367*bb4ee6a4SAndroid Build Coastguard Worker mem::size_of::<SmbiosEndOfTable>(),
368*bb4ee6a4SAndroid Build Coastguard Worker 0x4usize,
369*bb4ee6a4SAndroid Build Coastguard Worker concat!("Size of: ", stringify!(SmbiosEndOfTable))
370*bb4ee6a4SAndroid Build Coastguard Worker );
371*bb4ee6a4SAndroid Build Coastguard Worker }
372*bb4ee6a4SAndroid Build Coastguard Worker
373*bb4ee6a4SAndroid Build Coastguard Worker #[test]
entrypoint_checksum()374*bb4ee6a4SAndroid Build Coastguard Worker fn entrypoint_checksum() {
375*bb4ee6a4SAndroid Build Coastguard Worker let mem = GuestMemory::new(&[(GuestAddress(SMBIOS_START), 4096)]).unwrap();
376*bb4ee6a4SAndroid Build Coastguard Worker
377*bb4ee6a4SAndroid Build Coastguard Worker // Use default 3.0 SMBIOS format.
378*bb4ee6a4SAndroid Build Coastguard Worker setup_smbios(&mem, &SmbiosOptions::default(), 0).unwrap();
379*bb4ee6a4SAndroid Build Coastguard Worker
380*bb4ee6a4SAndroid Build Coastguard Worker let smbios_ep: Smbios30Entrypoint =
381*bb4ee6a4SAndroid Build Coastguard Worker mem.read_obj_from_addr(GuestAddress(SMBIOS_START)).unwrap();
382*bb4ee6a4SAndroid Build Coastguard Worker
383*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(compute_checksum(&smbios_ep), 0);
384*bb4ee6a4SAndroid Build Coastguard Worker }
385*bb4ee6a4SAndroid Build Coastguard Worker }
386