blob: 23ae1e610ac77b6fb354e5d63af156868cc07de7 [file] [log] [blame]
Simon Glass309e6ec2022-04-24 23:31:19 -06001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Bootmethod for EFI boot manager
4 *
5 * Copyright 2021 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
7 */
8
9#define LOG_CATEGORY UCLASS_BOOTSTD
10
Simon Glass309e6ec2022-04-24 23:31:19 -060011#include <bootdev.h>
12#include <bootflow.h>
13#include <bootmeth.h>
14#include <command.h>
15#include <dm.h>
Mark Kettenisf98bb0b2023-09-03 22:40:00 +020016#include <efi_loader.h>
17#include <efi_variable.h>
Ilias Apalodimas565938c2023-12-07 14:36:36 +020018#include <malloc.h>
Simon Glass309e6ec2022-04-24 23:31:19 -060019
Simon Glass161e1e32022-07-30 15:52:22 -060020/**
21 * struct efi_mgr_priv - private info for the efi-mgr driver
22 *
23 * @fake_bootflow: Fake a valid bootflow for testing
24 */
25struct efi_mgr_priv {
26 bool fake_dev;
27};
28
29void sandbox_set_fake_efi_mgr_dev(struct udevice *dev, bool fake_dev)
30{
31 struct efi_mgr_priv *priv = dev_get_priv(dev);
32
33 priv->fake_dev = fake_dev;
34}
35
Simon Glass309e6ec2022-04-24 23:31:19 -060036static int efi_mgr_check(struct udevice *dev, struct bootflow_iter *iter)
37{
38 int ret;
39
40 /* Must be an bootstd device */
Simon Glass18c50402023-01-17 10:47:54 -070041 ret = bootflow_iter_check_system(iter);
Simon Glass309e6ec2022-04-24 23:31:19 -060042 if (ret)
43 return log_msg_ret("net", ret);
44
45 return 0;
46}
47
48static int efi_mgr_read_bootflow(struct udevice *dev, struct bootflow *bflow)
49{
Simon Glass161e1e32022-07-30 15:52:22 -060050 struct efi_mgr_priv *priv = dev_get_priv(dev);
Mark Kettenisf98bb0b2023-09-03 22:40:00 +020051 efi_status_t ret;
52 efi_uintn_t size;
53 u16 *bootorder;
Simon Glass309e6ec2022-04-24 23:31:19 -060054
Simon Glass161e1e32022-07-30 15:52:22 -060055 if (priv->fake_dev) {
56 bflow->state = BOOTFLOWST_READY;
57 return 0;
58 }
59
Mark Kettenisf98bb0b2023-09-03 22:40:00 +020060 ret = efi_init_obj_list();
61 if (ret)
62 return log_msg_ret("init", ret);
63
64 /* Enable this method if the "BootOrder" UEFI exists. */
65 bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid,
66 &size);
67 if (bootorder) {
Ilias Apalodimas565938c2023-12-07 14:36:36 +020068 free(bootorder);
Mark Kettenisf98bb0b2023-09-03 22:40:00 +020069 bflow->state = BOOTFLOWST_READY;
70 return 0;
71 }
Simon Glass161e1e32022-07-30 15:52:22 -060072
73 return -EINVAL;
Simon Glass309e6ec2022-04-24 23:31:19 -060074}
75
76static int efi_mgr_read_file(struct udevice *dev, struct bootflow *bflow,
77 const char *file_path, ulong addr, ulong *sizep)
78{
79 /* Files are loaded by the 'bootefi bootmgr' command */
80
81 return -ENOSYS;
82}
83
84static int efi_mgr_boot(struct udevice *dev, struct bootflow *bflow)
85{
86 int ret;
87
88 /* Booting is handled by the 'bootefi bootmgr' command */
AKASHI Takahiro9f097bc2023-11-21 10:29:46 +090089 ret = efi_bootmgr_run(EFI_FDT_USE_INTERNAL);
Simon Glass309e6ec2022-04-24 23:31:19 -060090
91 return 0;
92}
93
94static int bootmeth_efi_mgr_bind(struct udevice *dev)
95{
96 struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
97
98 plat->desc = "EFI bootmgr flow";
Simon Glass4f8633d2022-07-30 15:52:21 -060099 plat->flags = BOOTMETHF_GLOBAL;
Simon Glass309e6ec2022-04-24 23:31:19 -0600100
101 return 0;
102}
103
104static struct bootmeth_ops efi_mgr_bootmeth_ops = {
105 .check = efi_mgr_check,
106 .read_bootflow = efi_mgr_read_bootflow,
107 .read_file = efi_mgr_read_file,
108 .boot = efi_mgr_boot,
109};
110
111static const struct udevice_id efi_mgr_bootmeth_ids[] = {
112 { .compatible = "u-boot,efi-bootmgr" },
113 { }
114};
115
Heinrich Schuchardtdc1f0062024-04-03 20:34:15 +0200116U_BOOT_DRIVER(bootmeth_3efi_mgr) = {
Simon Glass309e6ec2022-04-24 23:31:19 -0600117 .name = "bootmeth_efi_mgr",
118 .id = UCLASS_BOOTMETH,
119 .of_match = efi_mgr_bootmeth_ids,
120 .ops = &efi_mgr_bootmeth_ops,
121 .bind = bootmeth_efi_mgr_bind,
Simon Glass161e1e32022-07-30 15:52:22 -0600122 .priv_auto = sizeof(struct efi_mgr_priv),
Simon Glass309e6ec2022-04-24 23:31:19 -0600123};