]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/boot/boot-efi.c
use memzero(foo, length); for all memset(foo, 0, length); calls
[thirdparty/systemd.git] / src / boot / boot-efi.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Kay Sievers
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <stdlib.h>
23 #include <stdbool.h>
24 #include <unistd.h>
25 #include <getopt.h>
26 #include <locale.h>
27 #include <string.h>
28 #include <fnmatch.h>
29 #include <fcntl.h>
30 #include <sys/timex.h>
31
32 #include "boot.h"
33 #include "boot-loader.h"
34 #include "build.h"
35 #include "util.h"
36 #include "strv.h"
37 #include "efivars.h"
38 #include "conf-files.h"
39
40 static char *tilt_slashes(char *s) {
41 char *p;
42
43 if (!s)
44 return NULL;
45
46 for (p = s; *p; p++)
47 if (*p == '\\')
48 *p = '/';
49 return s;
50 }
51
52 static int get_boot_entries(struct boot_info *info) {
53 uint16_t *list;
54 int i, n;
55 int err = 0;
56
57 n = efi_get_boot_options(&list);
58 if (n < 0)
59 return n;
60
61 for (i = 0; i < n; i++) {
62 struct boot_info_entry *e;
63
64 e = realloc(info->fw_entries, (info->fw_entries_count+1) * sizeof(struct boot_info_entry));
65 if (!e) {
66 err = -ENOMEM;
67 break;
68 }
69 info->fw_entries = e;
70
71 e = &info->fw_entries[info->fw_entries_count];
72 memzero(e, sizeof(struct boot_info_entry));
73 e->order = -1;
74
75 err = efi_get_boot_option(list[i], &e->title, &e->part_uuid, &e->path);
76 if (err < 0)
77 continue;
78
79 if (isempty(e->title)) {
80 free(e->title);
81 e->title = NULL;
82 }
83 tilt_slashes(e->path);
84
85 e->id = list[i];
86 info->fw_entries_count++;
87 }
88
89 free(list);
90 return err;
91 }
92
93 static int find_active_entry(struct boot_info *info) {
94 uint16_t boot_cur;
95 void *buf;
96 size_t l;
97 size_t i;
98 int err;
99
100 err = efi_get_variable(EFI_VENDOR_GLOBAL, "BootCurrent", NULL, &buf, &l);
101 if (err < 0)
102 return err;
103
104 memcpy(&boot_cur, buf, sizeof(uint16_t));
105 for (i = 0; i < info->fw_entries_count; i++) {
106 if (info->fw_entries[i].id != boot_cur)
107 continue;
108 info->fw_entry_active = i;
109 err = 0;
110 break;
111 }
112 free(buf);
113 return err;
114 }
115
116 static int get_boot_order(struct boot_info *info) {
117 size_t i, k;
118 int r;
119
120 r = efi_get_boot_order(&info->fw_entries_order);
121 if (r < 0)
122 return r;
123
124 info->fw_entries_order_count = r;
125
126 for (i = 0; i < info->fw_entries_order_count; i++) {
127 for (k = 0; k < info->fw_entries_count; k++) {
128 if (info->fw_entries[k].id != info->fw_entries_order[i])
129 continue;
130 info->fw_entries[k].order = i;
131 break;
132 }
133 }
134
135 return 0;
136 }
137
138 static int entry_cmp(const void *a, const void *b) {
139 const struct boot_info_entry *e1 = a;
140 const struct boot_info_entry *e2 = b;
141
142 /* boot order of active entries */
143 if (e1->order > 0 && e2->order > 0)
144 return e1->order - e2->order;
145
146 /* sort active entries before inactive ones */
147 if (e1->order > 0)
148 return 1;
149 if (e2->order > 0)
150 return -1;
151
152 /* order of inactive entries */
153 return e1->id - e2->id;
154 }
155
156 int boot_info_query(struct boot_info *info) {
157 char str[64];
158 char buf[64];
159 char *loader_active = NULL;
160
161 info->fw_secure_boot = is_efi_secure_boot();
162 info->fw_secure_boot_setup_mode = is_efi_secure_boot_setup_mode();
163
164 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderInfo", &info->loader);
165
166 get_boot_entries(info);
167 if (info->fw_entries_count > 0) {
168 get_boot_order(info);
169 qsort(info->fw_entries, info->fw_entries_count, sizeof(struct boot_info_entry), entry_cmp);
170 find_active_entry(info);
171 }
172
173 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareType", &info->fw_type);
174 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareInfo", &info->fw_info);
175 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderImageIdentifier", &info->loader_image_path);
176 tilt_slashes(info->loader_image_path);
177 efi_loader_get_device_part_uuid(&info->loader_part_uuid);
178
179 boot_loader_read_entries(info);
180 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntrySelected", &loader_active);
181 if (loader_active) {
182 boot_loader_find_active_entry(info, loader_active);
183 free(loader_active);
184 }
185
186 snprintf(str, sizeof(str), "LoaderEntryOptions-%s", sd_id128_to_string(info->machine_id, buf));
187 efi_get_variable_string(EFI_VENDOR_LOADER, str, &info->loader_options_added);
188
189 return 0;
190 }