1 | // SPDX-License-Identifier: GPL-2.0-only |
---|---|
2 | // Copyright 2022 Google LLC |
3 | // Author: Ard Biesheuvel <ardb@google.com> |
4 | |
5 | #include <linux/efi.h> |
6 | |
7 | #include "efistub.h" |
8 | |
9 | typedef union efi_smbios_protocol efi_smbios_protocol_t; |
10 | |
11 | union efi_smbios_protocol { |
12 | struct { |
13 | efi_status_t (__efiapi *add)(efi_smbios_protocol_t *, efi_handle_t, |
14 | u16 *, struct efi_smbios_record *); |
15 | efi_status_t (__efiapi *update_string)(efi_smbios_protocol_t *, u16 *, |
16 | unsigned long *, u8 *); |
17 | efi_status_t (__efiapi *remove)(efi_smbios_protocol_t *, u16); |
18 | efi_status_t (__efiapi *get_next)(efi_smbios_protocol_t *, u16 *, u8 *, |
19 | struct efi_smbios_record **, |
20 | efi_handle_t *); |
21 | |
22 | u8 major_version; |
23 | u8 minor_version; |
24 | }; |
25 | struct { |
26 | u32 add; |
27 | u32 update_string; |
28 | u32 remove; |
29 | u32 get_next; |
30 | |
31 | u8 major_version; |
32 | u8 minor_version; |
33 | } mixed_mode; |
34 | }; |
35 | |
36 | const struct efi_smbios_record *efi_get_smbios_record(u8 type) |
37 | { |
38 | struct efi_smbios_record *record; |
39 | efi_smbios_protocol_t *smbios; |
40 | efi_status_t status; |
41 | u16 handle = 0xfffe; |
42 | |
43 | status = efi_bs_call(locate_protocol, &EFI_SMBIOS_PROTOCOL_GUID, NULL, |
44 | (void **)&smbios) ?: |
45 | efi_call_proto(smbios, get_next, &handle, &type, &record, NULL); |
46 | if (status != EFI_SUCCESS) |
47 | return NULL; |
48 | return record; |
49 | } |
50 | |
51 | const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record, |
52 | const u8 *offset) |
53 | { |
54 | const u8 *strtable; |
55 | |
56 | if (!record) |
57 | return NULL; |
58 | |
59 | strtable = (u8 *)record + record->length; |
60 | for (int i = 1; i < *offset; i++) { |
61 | int len = strlen(strtable); |
62 | |
63 | if (!len) |
64 | return NULL; |
65 | strtable += len + 1; |
66 | } |
67 | return strtable; |
68 | } |
69 |