Coverage Report

Created: 2026-03-11 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/u-boot/boot/bootmeth_efi_mgr.c
Line
Count
Source
1
// 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
11
#include <bootdev.h>
12
#include <bootflow.h>
13
#include <bootmeth.h>
14
#include <command.h>
15
#include <dm.h>
16
#include <efi_loader.h>
17
#include <efi_variable.h>
18
#include <malloc.h>
19
20
/**
21
 * struct efi_mgr_priv - private info for the efi-mgr driver
22
 *
23
 * @fake_bootflow: Fake a valid bootflow for testing
24
 */
25
struct efi_mgr_priv {
26
  bool fake_dev;
27
};
28
29
void sandbox_set_fake_efi_mgr_dev(struct udevice *dev, bool fake_dev)
30
0
{
31
0
  struct efi_mgr_priv *priv = dev_get_priv(dev);
32
33
0
  priv->fake_dev = fake_dev;
34
0
}
35
36
static int efi_mgr_check(struct udevice *dev, struct bootflow_iter *iter)
37
0
{
38
0
  int ret;
39
40
  /* Must be an bootstd device */
41
0
  ret = bootflow_iter_check_system(iter);
42
0
  if (ret)
43
0
    return log_msg_ret("net", ret);
44
45
0
  return 0;
46
0
}
47
48
static int efi_mgr_read_bootflow(struct udevice *dev, struct bootflow *bflow)
49
0
{
50
0
  struct efi_mgr_priv *priv = dev_get_priv(dev);
51
0
  efi_status_t ret;
52
0
  efi_uintn_t size;
53
0
  u16 *bootorder;
54
55
0
  if (priv->fake_dev) {
56
0
    bflow->state = BOOTFLOWST_READY;
57
0
    return 0;
58
0
  }
59
60
0
  ret = efi_init_obj_list();
61
0
  if (ret)
62
0
    return log_msg_ret("init", ret);
63
64
  /* Enable this method if the "BootOrder" UEFI exists. */
65
0
  bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid,
66
0
        &size);
67
0
  if (bootorder) {
68
0
    free(bootorder);
69
0
    bflow->state = BOOTFLOWST_READY;
70
0
    return 0;
71
0
  }
72
73
0
  return -EINVAL;
74
0
}
75
76
static int efi_mgr_read_file(struct udevice *dev, struct bootflow *bflow,
77
           const char *file_path, ulong addr,
78
           enum bootflow_img_t type, ulong *sizep)
79
0
{
80
  /* Files are loaded by the 'bootefi bootmgr' command */
81
82
0
  return -ENOSYS;
83
0
}
84
85
static int efi_mgr_boot(struct udevice *dev, struct bootflow *bflow)
86
0
{
87
0
  int ret;
88
89
  /* Booting is handled by the 'bootefi bootmgr' command */
90
0
  ret = efi_bootmgr_run(EFI_FDT_USE_INTERNAL);
91
92
0
  return 0;
93
0
}
94
95
static int bootmeth_efi_mgr_bind(struct udevice *dev)
96
0
{
97
0
  struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
98
99
0
  plat->desc = "EFI bootmgr flow";
100
0
  plat->flags = BOOTMETHF_GLOBAL;
101
102
  /*
103
   * bootmgr scans all available devices which can take a while,
104
   * especially for network devices. So choose the priority so that it
105
   * comes just before the 'very slow' devices. This allows systems which
106
   * don't rely on bootmgr to boot quickly, while allowing bootmgr to run
107
   * on systems which need it.
108
   */
109
0
  plat->glob_prio = BOOTDEVP_6_NET_BASE;
110
111
0
  return 0;
112
0
}
113
114
static struct bootmeth_ops efi_mgr_bootmeth_ops = {
115
  .check    = efi_mgr_check,
116
  .read_bootflow  = efi_mgr_read_bootflow,
117
  .read_file  = efi_mgr_read_file,
118
  .boot   = efi_mgr_boot,
119
};
120
121
static const struct udevice_id efi_mgr_bootmeth_ids[] = {
122
  { .compatible = "u-boot,efi-bootmgr" },
123
  { }
124
};
125
126
U_BOOT_DRIVER(bootmeth_3efi_mgr) = {
127
  .name   = "bootmeth_efi_mgr",
128
  .id   = UCLASS_BOOTMETH,
129
  .of_match = efi_mgr_bootmeth_ids,
130
  .ops    = &efi_mgr_bootmeth_ops,
131
  .bind   = bootmeth_efi_mgr_bind,
132
  .priv_auto  = sizeof(struct efi_mgr_priv),
133
};