summaryrefslogtreecommitdiffstats
path: root/src/boot
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2023-03-17 06:32:54 +0100
committerYu Watanabe <watanabe.yu+github@gmail.com>2023-03-17 12:40:34 +0100
commitc8eced395b8caa26b11b8876393438c2d73a72a8 (patch)
tree125dd281ab56ae31287d56a5a39331d3eaa03b2c /src/boot
parentbootctl: introduce uki_read_pretty_name() (diff)
downloadsystemd-c8eced395b8caa26b11b8876393438c2d73a72a8.tar.xz
systemd-c8eced395b8caa26b11b8876393438c2d73a72a8.zip
bootctl: introduce inspect_kernel()
Then, now verb_kernel_identify() and verb_kernel_inspect() can share most of the code.
Diffstat (limited to 'src/boot')
-rw-r--r--src/boot/bootctl-uki.c126
1 files changed, 87 insertions, 39 deletions
diff --git a/src/boot/bootctl-uki.c b/src/boot/bootctl-uki.c
index 65417b95b2..cfa491f22e 100644
--- a/src/boot/bootctl-uki.c
+++ b/src/boot/bootctl-uki.c
@@ -7,6 +7,7 @@
#include "os-util.h"
#include "parse-util.h"
#include "pe-header.h"
+#include "string-table.h"
#define MAX_SECTIONS 96
@@ -19,6 +20,22 @@ static const uint8_t name_initrd[8] = ".initrd";
static const uint8_t name_cmdline[8] = ".cmdline";
static const uint8_t name_uname[8] = ".uname";
+typedef enum KernelType {
+ KERNEL_TYPE_UNKNOWN,
+ KERNEL_TYPE_UKI,
+ KERNEL_TYPE_PE,
+ _KERNEL_TYPE_MAX,
+ _KERNEL_TYPE_INVALID = -EINVAL,
+} KernelType;
+
+static const char * const kernel_type_table[_KERNEL_TYPE_MAX] = {
+ [KERNEL_TYPE_UNKNOWN] = "unknown",
+ [KERNEL_TYPE_UKI] = "uki",
+ [KERNEL_TYPE_PE] = "pe",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(kernel_type, KernelType);
+
static int pe_sections(FILE *uki, struct PeSectionHeader **ret, size_t *ret_n) {
_cleanup_free_ struct PeSectionHeader *sections = NULL;
struct DosFileHeader dos;
@@ -207,7 +224,10 @@ static int uki_read_pretty_name(
static int inspect_uki(
FILE *uki,
struct PeSectionHeader *sections,
- size_t scount) {
+ size_t scount,
+ char **ret_cmdline,
+ char **ret_uname,
+ char **ret_pretty_name) {
_cleanup_free_ char *cmdline = NULL, *uname = NULL, *pname = NULL;
int r;
@@ -215,73 +235,101 @@ static int inspect_uki(
assert(uki);
assert(sections || scount == 0);
- r = read_pe_section(uki, sections, scount, name_cmdline, sizeof(name_cmdline), (void**) &cmdline, NULL);
- if (r < 0)
- return r;
+ if (ret_cmdline) {
+ r = read_pe_section(uki, sections, scount, name_cmdline, sizeof(name_cmdline), (void**) &cmdline, NULL);
+ if (r < 0)
+ return r;
+ }
- r = read_pe_section(uki, sections, scount, name_uname, sizeof(name_uname), (void**) &uname, NULL);
- if (r < 0)
- return r;
+ if (ret_uname) {
+ r = read_pe_section(uki, sections, scount, name_uname, sizeof(name_uname), (void**) &uname, NULL);
+ if (r < 0)
+ return r;
+ }
- r = uki_read_pretty_name(uki, sections, scount, &pname);
- if (r < 0)
- return r;
+ if (ret_pretty_name) {
+ r = uki_read_pretty_name(uki, sections, scount, &pname);
+ if (r < 0)
+ return r;
+ }
- if (cmdline)
- printf(" Cmdline: %s\n", cmdline);
- if (uname)
- printf(" Version: %s\n", uname);
- if (pname)
- printf(" OS: %s\n", pname);
+ if (ret_cmdline)
+ *ret_cmdline = TAKE_PTR(cmdline);
+ if (ret_uname)
+ *ret_uname = TAKE_PTR(uname);
+ if (ret_pretty_name)
+ *ret_pretty_name = TAKE_PTR(pname);
return 0;
}
-int verb_kernel_identify(int argc, char *argv[], void *userdata) {
+static int inspect_kernel(
+ const char *filename,
+ KernelType *ret_type,
+ char **ret_cmdline,
+ char **ret_uname,
+ char **ret_pretty_name) {
+
_cleanup_fclose_ FILE *uki = NULL;
_cleanup_free_ struct PeSectionHeader *sections = NULL;
size_t scount;
+ KernelType t;
int r;
- uki = fopen(argv[1], "re");
+ assert(filename);
+
+ uki = fopen(filename, "re");
if (!uki)
- return log_error_errno(errno, "Failed to open UKI file '%s': %m", argv[1]);
+ return log_error_errno(errno, "Failed to open UKI file '%s': %m", filename);
r = pe_sections(uki, &sections, &scount);
if (r < 0)
return r;
if (!sections)
- puts("unknown");
- else if (is_uki(sections, scount))
- puts("uki");
- else
- puts("pe");
+ t = KERNEL_TYPE_UNKNOWN;
+ else if (is_uki(sections, scount)) {
+ t = KERNEL_TYPE_UKI;
+ r = inspect_uki(uki, sections, scount, ret_cmdline, ret_uname, ret_pretty_name);
+ if (r < 0)
+ return r;
+ } else
+ t = KERNEL_TYPE_PE;
+
+ if (ret_type)
+ *ret_type = t;
return 0;
}
-int verb_kernel_inspect(int argc, char *argv[], void *userdata) {
- _cleanup_fclose_ FILE *uki = NULL;
- _cleanup_free_ struct PeSectionHeader *sections = NULL;
- size_t scount;
+int verb_kernel_identify(int argc, char *argv[], void *userdata) {
+ KernelType t;
int r;
- uki = fopen(argv[1], "re");
- if (!uki)
- return log_error_errno(errno, "Failed to open UKI file '%s': %m", argv[1]);
+ r = inspect_kernel(argv[1], &t, NULL, NULL, NULL);
+ if (r < 0)
+ return r;
- r = pe_sections(uki, &sections, &scount);
+ puts(kernel_type_to_string(t));
+ return 0;
+}
+
+int verb_kernel_inspect(int argc, char *argv[], void *userdata) {
+ _cleanup_free_ char *cmdline = NULL, *uname = NULL, *pname = NULL;
+ KernelType t;
+ int r;
+
+ r = inspect_kernel(argv[1], &t, &cmdline, &uname, &pname);
if (r < 0)
return r;
- if (!sections)
- puts("Kernel Type: unknown");
- else if (is_uki(sections, scount)) {
- puts("Kernel Type: uki");
- inspect_uki(uki, sections, scount);
- } else
- puts("Kernel Type: pe");
+ printf("Kernel Type: %s\n", kernel_type_to_string(t));
+ if (cmdline)
+ printf(" Cmdline: %s\n", cmdline);
+ if (uname)
+ printf(" Version: %s\n", uname);
+ if (pname)
+ printf(" OS: %s\n", pname);
return 0;
}