diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index f19af2a5566d..a5d2a476538f 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -1,225 +1,225 @@ # From: @(#)Makefile 5.20 (Berkeley) 6/12/93 # $FreeBSD$ .include SUBDIR= adduser \ arp \ binmiscctl \ camdd \ cdcontrol \ chkgrp \ chown \ chroot \ ckdist \ clear_locks \ crashinfo \ cron \ daemon \ dconschat \ devctl \ devinfo \ diskinfo \ dumpcis \ etcupdate \ extattr \ extattrctl \ fifolog \ fstyp \ fwcontrol \ getfmac \ getpmac \ gstat \ i2c \ ifmcstat \ iostat \ iovctl \ kldxref \ mailwrapper \ makefs \ memcontrol \ mergemaster \ mfiutil \ mixer \ mlxcontrol \ mountd \ mount_smbfs \ mpsutil \ mptutil \ mtest \ newsyslog \ nfscbd \ nfsd \ nfsdumpstate \ nfsrevoke \ nfsuserd \ nmtree \ nologin \ pciconf \ periodic \ pnfsdscopymr \ pnfsdsfile \ pnfsdskill \ powerd \ prometheus_sysctl_exporter \ pstat \ pw \ pwd_mkdb \ pwm \ quot \ rarpd \ rmt \ rpcbind \ rpc.lockd \ rpc.statd \ rpc.umntall \ rtprio \ rwhod \ service \ services_mkdb \ sesutil \ setfib \ setfmac \ setpmac \ smbmsg \ snapinfo \ spi \ spray \ syslogd \ sysrc \ tcpdrop \ tcpdump \ traceroute \ trim \ trpt \ tzsetup \ ugidfw \ valectl \ vigr \ vipw \ wake \ watch \ watchdogd \ zic \ zonectl # NB: keep these sorted by MK_* knobs SUBDIR.${MK_ACCT}+= accton SUBDIR.${MK_ACCT}+= sa SUBDIR.${MK_AUDIT}+= audit SUBDIR.${MK_AUDIT}+= auditd .if ${MK_OPENSSL} != "no" SUBDIR.${MK_AUDIT}+= auditdistd .endif SUBDIR.${MK_AUDIT}+= auditreduce SUBDIR.${MK_AUDIT}+= praudit SUBDIR.${MK_AUTHPF}+= authpf SUBDIR.${MK_AUTOFS}+= autofs SUBDIR.${MK_BLACKLIST}+= blacklistctl SUBDIR.${MK_BLACKLIST}+= blacklistd SUBDIR.${MK_BLUETOOTH}+= bluetooth SUBDIR.${MK_BOOTPARAMD}+= bootparamd SUBDIR.${MK_BSDINSTALL}+= bsdinstall SUBDIR.${MK_BSNMP}+= bsnmpd .if ${MK_CAROOT} != "no" SUBDIR.${MK_OPENSSL}+= certctl .endif SUBDIR.${MK_CXGBETOOL}+= cxgbetool SUBDIR.${MK_DIALOG}+= bsdconfig -SUBDIR.${MK_EFI}+= efivar efidp efibootmgr +SUBDIR.${MK_EFI}+= efivar efidp efibootmgr efitable .if ${MK_OPENSSL} != "no" SUBDIR.${MK_EFI}+= uefisign .endif SUBDIR.${MK_FLOPPY}+= fdcontrol SUBDIR.${MK_FLOPPY}+= fdformat SUBDIR.${MK_FLOPPY}+= fdread SUBDIR.${MK_FLOPPY}+= fdwrite SUBDIR.${MK_FREEBSD_UPDATE}+= freebsd-update SUBDIR.${MK_GSSAPI}+= gssd SUBDIR.${MK_GPIO}+= gpioctl SUBDIR.${MK_INET6}+= ip6addrctl SUBDIR.${MK_INET6}+= mld6query SUBDIR.${MK_INET6}+= ndp SUBDIR.${MK_INET6}+= rip6query SUBDIR.${MK_INET6}+= route6d SUBDIR.${MK_INET6}+= rrenumd SUBDIR.${MK_INET6}+= rtadvctl SUBDIR.${MK_INET6}+= rtadvd SUBDIR.${MK_INET6}+= rtsold SUBDIR.${MK_INET6}+= traceroute6 SUBDIR.${MK_INETD}+= inetd SUBDIR.${MK_IPFW}+= ipfwpcap SUBDIR.${MK_ISCSI}+= ctladm ctld iscsid SUBDIR.${MK_JAIL}+= jail SUBDIR.${MK_JAIL}+= jexec SUBDIR.${MK_JAIL}+= jls # XXX MK_SYSCONS SUBDIR.${MK_LEGACY_CONSOLE}+= kbdcontrol SUBDIR.${MK_LEGACY_CONSOLE}+= kbdmap SUBDIR.${MK_LEGACY_CONSOLE}+= moused SUBDIR.${MK_LEGACY_CONSOLE}+= vidcontrol SUBDIR.${MK_PPP}+= pppctl SUBDIR.${MK_NS_CACHING}+= nscd SUBDIR.${MK_LPR}+= lpr SUBDIR.${MK_MAN_UTILS}+= manctl SUBDIR.${MK_MLX5TOOL}+= mlx5tool SUBDIR.${MK_NETGRAPH}+= flowctl SUBDIR.${MK_NETGRAPH}+= ngctl SUBDIR.${MK_NETGRAPH}+= nghook SUBDIR.${MK_NIS}+= rpc.yppasswdd SUBDIR.${MK_NIS}+= rpc.ypupdated SUBDIR.${MK_NIS}+= rpc.ypxfrd SUBDIR.${MK_NIS}+= ypbind SUBDIR.${MK_NIS}+= ypldap SUBDIR.${MK_NIS}+= yp_mkdb SUBDIR.${MK_NIS}+= yppoll SUBDIR.${MK_NIS}+= yppush SUBDIR.${MK_NIS}+= ypserv SUBDIR.${MK_NIS}+= ypset SUBDIR.${MK_NTP}+= ntp SUBDIR.${MK_OPENSSL}+= keyserv SUBDIR.${MK_OPENSSL_KTLS}+= rpc.tlsclntd SUBDIR.${MK_OPENSSL_KTLS}+= rpc.tlsservd SUBDIR.${MK_PF}+= ftp-proxy SUBDIR.${MK_PKGBOOTSTRAP}+= pkg SUBDIR.${MK_PMC}+= pmc pmcannotate pmccontrol pmcstat pmcstudy SUBDIR.${MK_PORTSNAP}+= portsnap SUBDIR.${MK_PPP}+= ppp SUBDIR.${MK_QUOTAS}+= edquota SUBDIR.${MK_QUOTAS}+= quotaon SUBDIR.${MK_QUOTAS}+= repquota SUBDIR.${MK_SENDMAIL}+= editmap SUBDIR.${MK_SENDMAIL}+= mailstats SUBDIR.${MK_SENDMAIL}+= makemap SUBDIR.${MK_SENDMAIL}+= praliases SUBDIR.${MK_SENDMAIL}+= sendmail SUBDIR.${MK_TCP_WRAPPERS}+= tcpdchk SUBDIR.${MK_TCP_WRAPPERS}+= tcpdmatch SUBDIR.${MK_TOOLCHAIN}+= config SUBDIR.${MK_TOOLCHAIN}+= crunch SUBDIR.${MK_UNBOUND}+= unbound SUBDIR.${MK_USB}+= uathload SUBDIR.${MK_USB}+= uhsoctl SUBDIR.${MK_USB}+= usbconfig SUBDIR.${MK_USB}+= usbdump SUBDIR.${MK_UTMPX}+= ac SUBDIR.${MK_UTMPX}+= lastlogin SUBDIR.${MK_UTMPX}+= utx SUBDIR.${MK_WIRELESS}+= wlandebug SUBDIR.${MK_WIRELESS}+= wpa SUBDIR.${MK_TESTS}+= tests .include # Add architecture-specific manpages # to be included anyway MAN= apmd/apmd.8 \ nvram/nvram.8 .include SUBDIR_PARALLEL= .include diff --git a/usr.sbin/efitable/Makefile b/usr.sbin/efitable/Makefile new file mode 100644 index 000000000000..83db6d9f74a6 --- /dev/null +++ b/usr.sbin/efitable/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +PROG= efitable +MAN= efitable.8 +SRCS= efitable.c + +LIBADD= xo + +.include diff --git a/usr.sbin/efitable/efitable.8 b/usr.sbin/efitable/efitable.8 new file mode 100644 index 000000000000..2bea4f9fb2c1 --- /dev/null +++ b/usr.sbin/efitable/efitable.8 @@ -0,0 +1,70 @@ +.\" +.\" Copyright (c) 2021 3mdeb Embedded Systems Consulting +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd June 10, 2021 +.Dt EFITABLE 8 +.Os +.Sh NAME +.Nm efitable +.Nd Dump UEFI tables +.Sh SYNOPSIS +.Nm +.Op Fl u Ar uuid | Fl t Ar name +.Op Fl -libxo +.Sh DESCRIPTION +This program prints data from +.Dq Unified Extensible Firmware Interface +.Pq UEFI +tables. +.Pp +The following options are available: +.Bl -tag -width 20m +.It Fl -libxo +Generate output via +.Xr libxo 3 +in a selection of different human and machine readable formats. +See +.Xr xo_parse_args 3 +for details on command line arguments. +.It Fl t Ar name Fl -table Ar name +Specify the name of the table to print. +Currently supported tables: +.Pp +.Bl -tag -width indent -compact +.It Cm esrt +EFI System Resource Table +.It Cm prop +EFI Properties Table +.El +.It Fl Ar uuid Fl -uuid Ar uuid +Specify the UUID of the table to print. +.El +.Pp +.Sh HISTORY +The +.Nm +utility first appeared in +.Fx 14.0 . diff --git a/usr.sbin/efitable/efitable.c b/usr.sbin/efitable/efitable.c new file mode 100644 index 000000000000..367ce3f033b1 --- /dev/null +++ b/usr.sbin/efitable/efitable.c @@ -0,0 +1,239 @@ +/*- + * Copyright (c) 2021 3mdeb Embedded Systems Consulting + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TABLE_MAX_LEN 30 +#define EFITABLE_XO_VERSION "1" + +static void efi_table_print_esrt(const void *data); +static void efi_table_print_prop(const void *data); +static void usage(void); + +struct efi_table_op { + char name[TABLE_MAX_LEN]; + void (*parse) (const void *); + struct uuid uuid; +}; + +static const struct efi_table_op efi_table_ops[] = { + { .name = "esrt", .parse = efi_table_print_esrt, + .uuid = EFI_TABLE_ESRT }, + { .name = "prop", .parse = efi_table_print_prop, + .uuid = EFI_PROPERTIES_TABLE } +}; + +int +main(int argc, char **argv) +{ + struct efi_get_table_ioc table = { + .buf = NULL, + .buf_len = 0, + .table_len = 0 + }; + int efi_fd, ch, rc = 1, efi_idx = -1; + bool got_table = false; + bool table_set = false; + bool uuid_set = false; + struct option longopts[] = { + { "uuid", required_argument, NULL, 'u' }, + { "table", required_argument, NULL, 't' }, + { NULL, 0, NULL, 0 } + }; + + argc = xo_parse_args(argc, argv); + if (argc < 0) + exit(EXIT_FAILURE); + + while ((ch = getopt_long(argc, argv, "u:t:", longopts, NULL)) != -1) { + switch (ch) { + case 'u': + { + char *uuid_str = optarg; + struct uuid uuid; + uint32_t status; + + uuid_set = 1; + + uuid_from_string(uuid_str, &uuid, &status); + if (status != uuid_s_ok) + xo_errx(EX_DATAERR, "invalid UUID"); + + for (size_t n = 0; n < nitems(efi_table_ops); n++) { + if (!memcmp(&uuid, &efi_table_ops[n].uuid, + sizeof(uuid))) { + efi_idx = n; + got_table = true; + break; + } + } + break; + } + case 't': + { + char *table_name = optarg; + + table_set = true; + + for (size_t n = 0; n < nitems(efi_table_ops); n++) { + if (!strcmp(table_name, + efi_table_ops[n].name)) { + efi_idx = n; + got_table = true; + break; + } + } + + if (!got_table) + xo_errx(EX_DATAERR, "unsupported efi table"); + + break; + } + default: + usage(); + } + } + + if (!table_set && !uuid_set) + xo_errx(EX_USAGE, "table is not set"); + + if (!got_table) + xo_errx(EX_DATAERR, "unsupported table"); + + efi_fd = open("/dev/efi", O_RDWR); + if (efi_fd < 0) + xo_err(EX_OSFILE, "/dev/efi"); + + table.uuid = efi_table_ops[efi_idx].uuid; + if (ioctl(efi_fd, EFIIOC_GET_TABLE, &table) == -1) + xo_err(EX_OSERR, NULL); + + table.buf = malloc(table.table_len); + table.buf_len = table.table_len; + + if (ioctl(efi_fd, EFIIOC_GET_TABLE, &table) == -1) + xo_err(EX_OSERR, NULL); + + efi_table_ops[efi_idx].parse(table.buf); + close(efi_fd); + + return (rc); +} + +static void +efi_table_print_esrt(const void *data) +{ + const struct efi_esrt_entry_v1 *entries_v1; + const struct efi_esrt_table *esrt; + + esrt = (const struct efi_esrt_table *)data; + + xo_set_version(EFITABLE_XO_VERSION); + xo_open_container("esrt"); + xo_emit("{Lwc:FwResourceCount}{:fw_resource_count/%u}\n", + esrt->fw_resource_count); + xo_emit("{Lwc:FwResourceCountMax}{:fw_resource_count_max/%u}\n", + esrt->fw_resource_count_max); + xo_emit("{Lwc:FwResourceVersion}{:fw_resource_version/%u}\n", + esrt->fw_resource_version); + xo_open_list("entries"); + xo_emit("\nEntries:\n"); + + entries_v1 = (const void *) esrt->entries; + for (uint32_t i = 0; i < esrt->fw_resource_count; i++) { + const struct efi_esrt_entry_v1 *e = &entries_v1[i]; + uint32_t status; + char *uuid; + + uuid_to_string(&e->fw_class, &uuid, &status); + if (status != uuid_s_ok) { + xo_errx(EX_DATAERR, "uuid_to_string error"); + } + + xo_open_instance("entries"); + xo_emit("\n"); + xo_emit("{P: }{Lwc:FwClass}{:fw_class/%s}\n", uuid); + xo_emit("{P: }{Lwc:FwType}{:fw_type/%u}\n", e->fw_type); + xo_emit("{P: }{Lwc:FwVersion}{:fw_version/%u}\n", + e->fw_version); + xo_emit("{P: }{Lwc:LowestSupportedFwVersion}" + "{:lowest_supported_fw_version/%u}\n", + e->lowest_supported_fw_version); + xo_emit("{P: }{Lwc:CapsuleFlags}{:capsule_flags/%#x}\n", + e->capsule_flags); + xo_emit("{P: }{Lwc:LastAttemptVersion" + "}{:last_attempt_version/%u}\n", e->last_attempt_version); + xo_emit("{P: }{Lwc:LastAttemptStatus" + "}{:last_attempt_status/%u}\n", e->last_attempt_status); + + xo_close_instance("entries"); + } + + xo_close_list("entries"); + xo_close_container("esrt"); + xo_finish(); +} + +static void +efi_table_print_prop(const void *data) +{ + const struct efi_prop_table *prop; + + prop = (const struct efi_prop_table *)data; + + xo_set_version(EFITABLE_XO_VERSION); + xo_open_container("prop"); + xo_emit("{Lwc:Version}{:version/%#x}\n", prop->version); + xo_emit("{Lwc:Length}{:length/%u}\n", prop->length); + xo_emit("{Lwc:MemoryProtectionAttribute}" + "{:memory_protection_attribute/%#lx}\n", + prop->memory_protection_attribute); + xo_close_container("prop"); + xo_finish(); +} + +static void usage(void) +{ + xo_error("usage: efitable [-d uuid | -t name] [--libxo]\n"); + exit(EX_USAGE); +}