]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/efitable/efitable.c
Import libfido2 at 'contrib/libfido2/'
[FreeBSD/FreeBSD.git] / usr.sbin / efitable / efitable.c
1 /*-
2  * Copyright (c) 2021 3mdeb Embedded Systems Consulting <contact@3mdeb.com>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 #include <sys/types.h>
30 #include <sys/efi.h>
31 #include <sys/efiio.h>
32 #include <sys/param.h>
33 #include <sys/stat.h>
34 #include <err.h>
35 #include <fcntl.h>
36 #include <getopt.h>
37 #include <stdbool.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sysexits.h>
42 #include <unistd.h>
43 #include <uuid.h>
44 #include <libxo/xo.h>
45
46 #define TABLE_MAX_LEN 30
47 #define EFITABLE_XO_VERSION "1"
48
49 static void efi_table_print_esrt(const void *data);
50 static void efi_table_print_prop(const void *data);
51 static void usage(void);
52
53 struct efi_table_op {
54         char name[TABLE_MAX_LEN];
55         void (*parse) (const void *);
56         struct uuid uuid;
57 };
58
59 static const struct efi_table_op efi_table_ops[] = {
60         { .name = "esrt", .parse = efi_table_print_esrt,
61             .uuid = EFI_TABLE_ESRT },
62         { .name = "prop", .parse = efi_table_print_prop,
63             .uuid = EFI_PROPERTIES_TABLE }
64 };
65
66 int
67 main(int argc, char **argv)
68 {
69         struct efi_get_table_ioc table = {
70                 .buf = NULL,
71                 .buf_len = 0,
72                 .table_len = 0
73         };
74         int efi_fd, ch, rc = 1, efi_idx = -1;
75         bool got_table = false;
76         bool table_set = false;
77         bool uuid_set = false;
78         struct option longopts[] = {
79                 { "uuid",  required_argument, NULL, 'u' },
80                 { "table", required_argument, NULL, 't' },
81                 { NULL,    0,                 NULL,  0  }
82         };
83
84         argc = xo_parse_args(argc, argv);
85         if (argc < 0)
86                 exit(EXIT_FAILURE);
87
88         while ((ch = getopt_long(argc, argv, "u:t:", longopts, NULL)) != -1) {
89                 switch (ch) {
90                 case 'u':
91                 {
92                         char *uuid_str = optarg;
93                         struct uuid uuid;
94                         uint32_t status;
95
96                         uuid_set = 1;
97
98                         uuid_from_string(uuid_str, &uuid, &status);
99                         if (status != uuid_s_ok)
100                                 xo_errx(EX_DATAERR, "invalid UUID");
101
102                         for (size_t n = 0; n < nitems(efi_table_ops); n++) {
103                                 if (!memcmp(&uuid, &efi_table_ops[n].uuid,
104                                     sizeof(uuid))) {
105                                         efi_idx = n;
106                                         got_table = true;
107                                         break;
108                                 }
109                         }
110                         break;
111                 }
112                 case 't':
113                 {
114                         char *table_name = optarg;
115
116                         table_set = true;
117
118                         for (size_t n = 0; n < nitems(efi_table_ops); n++) {
119                                 if (!strcmp(table_name,
120                                     efi_table_ops[n].name)) {
121                                         efi_idx = n;
122                                         got_table = true;
123                                         break;
124                                 }
125                         }
126
127                         if (!got_table)
128                                 xo_errx(EX_DATAERR, "unsupported efi table");
129
130                         break;
131                 }
132                 default:
133                         usage();
134                 }
135         }
136
137         if (!table_set && !uuid_set)
138                 xo_errx(EX_USAGE, "table is not set");
139
140         if (!got_table)
141                 xo_errx(EX_DATAERR, "unsupported table");
142
143         efi_fd = open("/dev/efi", O_RDWR);
144         if (efi_fd < 0)
145                 xo_err(EX_OSFILE, "/dev/efi");
146
147         table.uuid = efi_table_ops[efi_idx].uuid;
148         if (ioctl(efi_fd, EFIIOC_GET_TABLE, &table) == -1)
149                 xo_err(EX_OSERR, "EFIIOC_GET_TABLE (len == 0)");
150
151         table.buf = malloc(table.table_len);
152         table.buf_len = table.table_len;
153
154         if (ioctl(efi_fd, EFIIOC_GET_TABLE, &table) == -1)
155                 xo_err(EX_OSERR, "EFIIOC_GET_TABLE");
156
157         efi_table_ops[efi_idx].parse(table.buf);
158         close(efi_fd);
159
160         return (rc);
161 }
162
163 static void
164 efi_table_print_esrt(const void *data)
165 {
166         const struct efi_esrt_entry_v1 *entries_v1;
167         const struct efi_esrt_table *esrt;
168
169         esrt = (const struct efi_esrt_table *)data;
170
171         xo_set_version(EFITABLE_XO_VERSION);
172         xo_open_container("esrt");
173         xo_emit("{Lwc:FwResourceCount}{:fw_resource_count/%u}\n",
174             esrt->fw_resource_count);
175         xo_emit("{Lwc:FwResourceCountMax}{:fw_resource_count_max/%u}\n",
176             esrt->fw_resource_count_max);
177         xo_emit("{Lwc:FwResourceVersion}{:fw_resource_version/%u}\n",
178             esrt->fw_resource_version);
179         xo_open_list("entries");
180         xo_emit("\nEntries:\n");
181
182         entries_v1 = (const void *) esrt->entries;
183         for (uint32_t i = 0; i < esrt->fw_resource_count; i++) {
184                 const struct efi_esrt_entry_v1 *e = &entries_v1[i];
185                 uint32_t status;
186                 char *uuid;
187
188                 uuid_to_string(&e->fw_class, &uuid, &status);
189                 if (status != uuid_s_ok) {
190                         xo_errx(EX_DATAERR, "uuid_to_string error");
191                 }
192
193                 xo_open_instance("entries");
194                 xo_emit("\n");
195                 xo_emit("{P:  }{Lwc:FwClass}{:fw_class/%s}\n", uuid);
196                 xo_emit("{P:  }{Lwc:FwType}{:fw_type/%u}\n", e->fw_type);
197                 xo_emit("{P:  }{Lwc:FwVersion}{:fw_version/%u}\n",
198                     e->fw_version);
199                 xo_emit("{P:  }{Lwc:LowestSupportedFwVersion}"
200                     "{:lowest_supported_fw_version/%u}\n",
201                     e->lowest_supported_fw_version);
202                 xo_emit("{P:  }{Lwc:CapsuleFlags}{:capsule_flags/%#x}\n",
203                     e->capsule_flags);
204                 xo_emit("{P:  }{Lwc:LastAttemptVersion"
205                     "}{:last_attempt_version/%u}\n", e->last_attempt_version);
206                 xo_emit("{P:  }{Lwc:LastAttemptStatus"
207                     "}{:last_attempt_status/%u}\n", e->last_attempt_status);
208
209                 xo_close_instance("entries");
210         }
211
212         xo_close_list("entries");
213         xo_close_container("esrt");
214         xo_finish();
215 }
216
217 static void
218 efi_table_print_prop(const void *data)
219 {
220         const struct efi_prop_table *prop;
221
222         prop = (const struct efi_prop_table *)data;
223
224         xo_set_version(EFITABLE_XO_VERSION);
225         xo_open_container("prop");
226         xo_emit("{Lwc:Version}{:version/%#x}\n", prop->version);
227         xo_emit("{Lwc:Length}{:length/%u}\n", prop->length);
228         xo_emit("{Lwc:MemoryProtectionAttribute}"
229             "{:memory_protection_attribute/%#lx}\n",
230             prop->memory_protection_attribute);
231         xo_close_container("prop");
232         xo_finish();
233 }
234
235 static void usage(void)
236 {
237         xo_error("usage: efitable [-d uuid | -t name] [--libxo]\n");
238         exit(EX_USAGE);
239 }