xref: /freebsd/stand/efi/boot1/boot1.c (revision 67ca7330cf34a789afbbff9ae7e4cdc4a4917ae3)
1 /*-
2  * Copyright (c) 1998 Robert Nordier
3  * All rights reserved.
4  * Copyright (c) 2001 Robert Drehmel
5  * All rights reserved.
6  * Copyright (c) 2014 Nathan Whitehorn
7  * All rights reserved.
8  * Copyright (c) 2015 Eric McCorkle
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms are freely
12  * permitted provided that the above copyright notice and this
13  * paragraph and the following disclaimer are duplicated in all
14  * such forms.
15  *
16  * This software is provided "AS IS" and without any express or
17  * implied warranties, including, without limitation, the implied
18  * warranties of merchantability and fitness for a particular
19  * purpose.
20  */
21 
22 #include <sys/cdefs.h>
23 __FBSDID("$FreeBSD$");
24 
25 #include <sys/param.h>
26 #include <machine/elf.h>
27 #include <machine/stdarg.h>
28 #include <stand.h>
29 
30 #include <efi.h>
31 #include <eficonsctl.h>
32 #include <efichar.h>
33 
34 #include "boot_module.h"
35 #include "paths.h"
36 
37 static void efi_panic(EFI_STATUS s, const char *fmt, ...) __dead2 __printflike(2, 3);
38 
39 static const boot_module_t *boot_modules[] =
40 {
41 #ifdef EFI_ZFS_BOOT
42 	&zfs_module,
43 #endif
44 #ifdef EFI_UFS_BOOT
45 	&ufs_module
46 #endif
47 };
48 
49 #define	NUM_BOOT_MODULES	nitems(boot_modules)
50 
51 static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
52 static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
53 static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
54 static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
55 
56 /*
57  * Provide Malloc / Free / Calloc backed by EFIs AllocatePool / FreePool which ensures
58  * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
59  * EFI methods.
60  */
61 
62 void *
63 Malloc(size_t len, const char *file __unused, int line __unused)
64 {
65 	void *out;
66 
67 	if (BS->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS)
68 		return (out);
69 
70 	return (NULL);
71 }
72 
73 void
74 Free(void *buf, const char *file __unused, int line __unused)
75 {
76 	if (buf != NULL)
77 		(void)BS->FreePool(buf);
78 }
79 
80 void *
81 Calloc(size_t n1, size_t n2, const char *file, int line)
82 {
83 	size_t bytes;
84 	void *res;
85 
86 	bytes = n1 * n2;
87 	if ((res = Malloc(bytes, file, line)) != NULL)
88 		bzero(res, bytes);
89 
90 	return (res);
91 }
92 
93 /*
94  * load_loader attempts to load the loader image data.
95  *
96  * It tries each module and its respective devices, identified by mod->probe,
97  * in order until a successful load occurs at which point it returns EFI_SUCCESS
98  * and EFI_NOT_FOUND otherwise.
99  *
100  * Only devices which have preferred matching the preferred parameter are tried.
101  */
102 static EFI_STATUS
103 load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp,
104     size_t *bufsize, int preferred)
105 {
106 	UINTN i;
107 	dev_info_t *dev;
108 	const boot_module_t *mod;
109 
110 	for (i = 0; i < NUM_BOOT_MODULES; i++) {
111 		mod = boot_modules[i];
112 		for (dev = mod->devices(); dev != NULL; dev = dev->next) {
113 			if (dev->preferred != preferred)
114 				continue;
115 
116 			if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) ==
117 			    EFI_SUCCESS) {
118 				*devinfop = dev;
119 				*modp = mod;
120 				return (EFI_SUCCESS);
121 			}
122 		}
123 	}
124 
125 	return (EFI_NOT_FOUND);
126 }
127 
128 /*
129  * try_boot only returns if it fails to load the loader. If it succeeds
130  * it simply boots, otherwise it returns the status of last EFI call.
131  */
132 static EFI_STATUS
133 try_boot(void)
134 {
135 	size_t bufsize, loadersize, cmdsize;
136 	void *buf, *loaderbuf;
137 	char *cmd;
138 	dev_info_t *dev;
139 	const boot_module_t *mod;
140 	EFI_HANDLE loaderhandle;
141 	EFI_LOADED_IMAGE *loaded_image;
142 	EFI_STATUS status;
143 
144 	status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 1);
145 	if (status != EFI_SUCCESS) {
146 		status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 0);
147 		if (status != EFI_SUCCESS) {
148 			printf("Failed to load '%s'\n", PATH_LOADER_EFI);
149 			return (status);
150 		}
151 	}
152 
153 	/*
154 	 * Read in and parse the command line from /boot.config or /boot/config,
155 	 * if present. We'll pass it the next stage via a simple ASCII
156 	 * string. loader.efi has a hack for ASCII strings, so we'll use that to
157 	 * keep the size down here. We only try to read the alternate file if
158 	 * we get EFI_NOT_FOUND because all other errors mean that the boot_module
159 	 * had troubles with the filesystem. We could return early, but we'll let
160 	 * loading the actual kernel sort all that out. Since these files are
161 	 * optional, we don't report errors in trying to read them.
162 	 */
163 	cmd = NULL;
164 	cmdsize = 0;
165 	status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize);
166 	if (status == EFI_NOT_FOUND)
167 		status = mod->load(PATH_CONFIG, dev, &buf, &bufsize);
168 	if (status == EFI_SUCCESS) {
169 		cmdsize = bufsize + 1;
170 		cmd = malloc(cmdsize);
171 		if (cmd == NULL)
172 			goto errout;
173 		memcpy(cmd, buf, bufsize);
174 		cmd[bufsize] = '\0';
175 		free(buf);
176 		buf = NULL;
177 	}
178 
179 	if ((status = BS->LoadImage(TRUE, IH, efi_devpath_last_node(dev->devpath),
180 	    loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) {
181 		printf("Failed to load image provided by %s, size: %zu, (%lu)\n",
182 		     mod->name, loadersize, EFI_ERROR_CODE(status));
183 		goto errout;
184 	}
185 
186 	if ((status = BS->HandleProtocol(loaderhandle, &LoadedImageGUID,
187 	    (VOID**)&loaded_image)) != EFI_SUCCESS) {
188 		printf("Failed to query LoadedImage provided by %s (%lu)\n",
189 		    mod->name, EFI_ERROR_CODE(status));
190 		goto errout;
191 	}
192 
193 	if (cmd != NULL)
194 		printf("    command args: %s\n", cmd);
195 
196 	loaded_image->DeviceHandle = dev->devhandle;
197 	loaded_image->LoadOptionsSize = cmdsize;
198 	loaded_image->LoadOptions = cmd;
199 
200 	DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
201 	DSTALL(1000000);
202 	DPRINTF(".");
203 	DSTALL(1000000);
204 	DPRINTF(".");
205 	DSTALL(1000000);
206 	DPRINTF(".");
207 	DSTALL(1000000);
208 	DPRINTF(".");
209 	DSTALL(1000000);
210 	DPRINTF(".\n");
211 
212 	if ((status = BS->StartImage(loaderhandle, NULL, NULL)) !=
213 	    EFI_SUCCESS) {
214 		printf("Failed to start image provided by %s (%lu)\n",
215 		    mod->name, EFI_ERROR_CODE(status));
216 		loaded_image->LoadOptionsSize = 0;
217 		loaded_image->LoadOptions = NULL;
218 	}
219 
220 errout:
221 	if (cmd != NULL)
222 		free(cmd);
223 	if (buf != NULL)
224 		free(buf);
225 	if (loaderbuf != NULL)
226 		free(loaderbuf);
227 
228 	return (status);
229 }
230 
231 /*
232  * probe_handle determines if the passed handle represents a logical partition
233  * if it does it uses each module in order to probe it and if successful it
234  * returns 0.
235  */
236 static int
237 probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
238 {
239 	dev_info_t *devinfo;
240 	EFI_BLOCK_IO *blkio;
241 	EFI_DEVICE_PATH *devpath;
242 	EFI_STATUS status;
243 	UINTN i;
244 	int preferred;
245 
246 	/* Figure out if we're dealing with an actual partition. */
247 	status = BS->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
248 	if (status == EFI_UNSUPPORTED)
249 		return (0);
250 
251 	if (status != EFI_SUCCESS) {
252 		DPRINTF("\nFailed to query DevicePath (%lu)\n",
253 		    EFI_ERROR_CODE(status));
254 		return (-1);
255 	}
256 #ifdef EFI_DEBUG
257 	{
258 		CHAR16 *text = efi_devpath_name(devpath);
259 		DPRINTF("probing: %S ", text);
260 		efi_free_devpath_name(text);
261 	}
262 #endif
263 	status = BS->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
264 	if (status == EFI_UNSUPPORTED)
265 		return (0);
266 
267 	if (status != EFI_SUCCESS) {
268 		DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
269 		    EFI_ERROR_CODE(status));
270 		return (-1);
271 	}
272 
273 	if (!blkio->Media->LogicalPartition)
274 		return (0);
275 
276 	preferred = efi_devpath_same_disk(imgpath, devpath);
277 
278 	/* Run through each module, see if it can load this partition */
279 	devinfo = malloc(sizeof(*devinfo));
280 	if (devinfo == NULL) {
281 		DPRINTF("\nFailed to allocate devinfo\n");
282 		return (-1);
283 	}
284 	devinfo->dev = blkio;
285 	devinfo->devpath = devpath;
286 	devinfo->devhandle = h;
287 	devinfo->preferred = preferred;
288 	devinfo->next = NULL;
289 
290 	for (i = 0; i < NUM_BOOT_MODULES; i++) {
291 		devinfo->devdata = NULL;
292 
293 		status = boot_modules[i]->probe(devinfo);
294 		if (status == EFI_SUCCESS)
295 			return (preferred + 1);
296 	}
297 	free(devinfo);
298 
299 	return (0);
300 }
301 
302 const char *prio_str[] = {
303 	"error",
304 	"not supported",
305 	"good",
306 	"better"
307 };
308 
309 EFI_STATUS
310 efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
311 {
312 	EFI_HANDLE *handles;
313 	EFI_LOADED_IMAGE *img;
314 	EFI_DEVICE_PATH *imgpath;
315 	EFI_STATUS status;
316 	EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
317 	SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
318 	UINTN i, hsize, nhandles;
319 	CHAR16 *text;
320 	UINT16 boot_current;
321 	size_t sz;
322 	UINT16 boot_order[100];
323 	int rv;
324 
325 	/* Basic initialization*/
326 	ST = Xsystab;
327 	IH = Ximage;
328 	BS = ST->BootServices;
329 	RS = ST->RuntimeServices;
330 
331 	/* Set up the console, so printf works. */
332 	status = BS->LocateProtocol(&ConsoleControlGUID, NULL,
333 	    (VOID **)&ConsoleControl);
334 	if (status == EFI_SUCCESS)
335 		(void)ConsoleControl->SetMode(ConsoleControl,
336 		    EfiConsoleControlScreenText);
337 	/*
338 	 * Reset the console enable the cursor. Later we'll choose a better
339 	 * console size through GOP/UGA.
340 	 */
341 	conout = ST->ConOut;
342 	conout->Reset(conout, TRUE);
343 	/* Explicitly set conout to mode 0, 80x25 */
344 	conout->SetMode(conout, 0);
345 	conout->EnableCursor(conout, TRUE);
346 	conout->ClearScreen(conout);
347 
348 	printf("\n>> FreeBSD EFI boot block\n");
349 	printf("   Loader path: %s\n\n", PATH_LOADER_EFI);
350 	printf("   Initializing modules:");
351 	for (i = 0; i < NUM_BOOT_MODULES; i++) {
352 		printf(" %s", boot_modules[i]->name);
353 		if (boot_modules[i]->init != NULL)
354 			boot_modules[i]->init();
355 	}
356 	putchar('\n');
357 
358 	/* Determine the devpath of our image so we can prefer it. */
359 	status = BS->HandleProtocol(IH, &LoadedImageGUID, (VOID**)&img);
360 	imgpath = NULL;
361 	if (status == EFI_SUCCESS) {
362 		text = efi_devpath_name(img->FilePath);
363 		if (text != NULL) {
364 			printf("   Load Path: %S\n", text);
365 			efi_setenv_freebsd_wcs("Boot1Path", text);
366 			efi_free_devpath_name(text);
367 		}
368 
369 		status = BS->HandleProtocol(img->DeviceHandle, &DevicePathGUID,
370 		    (void **)&imgpath);
371 		if (status != EFI_SUCCESS) {
372 			DPRINTF("Failed to get image DevicePath (%lu)\n",
373 			    EFI_ERROR_CODE(status));
374 		} else {
375 			text = efi_devpath_name(imgpath);
376 			if (text != NULL) {
377 				printf("   Load Device: %S\n", text);
378 				efi_setenv_freebsd_wcs("Boot1Dev", text);
379 				efi_free_devpath_name(text);
380 			}
381 		}
382 	}
383 
384 	boot_current = 0;
385 	sz = sizeof(boot_current);
386 	if (efi_global_getenv("BootCurrent", &boot_current, &sz) == EFI_SUCCESS) {
387 		printf("   BootCurrent: %04x\n", boot_current);
388 
389 		sz = sizeof(boot_order);
390 		if (efi_global_getenv("BootOrder", &boot_order, &sz) == EFI_SUCCESS) {
391 			printf("   BootOrder:");
392 			for (i = 0; i < sz / sizeof(boot_order[0]); i++)
393 				printf(" %04x%s", boot_order[i],
394 				    boot_order[i] == boot_current ? "[*]" : "");
395 			printf("\n");
396 		}
397 	}
398 
399 #ifdef TEST_FAILURE
400 	/*
401 	 * For testing failover scenarios, it's nice to be able to fail fast.
402 	 * Define TEST_FAILURE to create a boot1.efi that always fails after
403 	 * reporting the boot manager protocol details.
404 	 */
405 	BS->Exit(IH, EFI_OUT_OF_RESOURCES, 0, NULL);
406 #endif
407 
408 	hsize = 0;
409 	BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
410 	    &hsize, NULL);
411 	handles = malloc(hsize);
412 	if (handles == NULL)
413 		efi_panic(EFI_OUT_OF_RESOURCES, "Failed to allocate %d handles\n",
414 		    hsize);
415 	status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
416 	    NULL, &hsize, handles);
417 	if (status != EFI_SUCCESS)
418 		efi_panic(status, "Failed to get device handles\n");
419 
420 	/* Scan all partitions, probing with all modules. */
421 	nhandles = hsize / sizeof(*handles);
422 	printf("   Probing %zu block devices...", nhandles);
423 	DPRINTF("\n");
424 
425 	for (i = 0; i < nhandles; i++) {
426 		rv = probe_handle(handles[i], imgpath);
427 #ifdef EFI_DEBUG
428 		printf("%c", "x.+*"[rv + 1]);
429 #else
430 		printf("%s\n", prio_str[rv + 1]);
431 #endif
432 	}
433 	printf(" done\n");
434 
435 	/* Status summary. */
436 	for (i = 0; i < NUM_BOOT_MODULES; i++) {
437 		printf("    ");
438 		boot_modules[i]->status();
439 	}
440 
441 	try_boot();
442 
443 	/* If we get here, we're out of luck... */
444 	efi_panic(EFI_LOAD_ERROR, "No bootable partitions found!");
445 }
446 
447 /*
448  * add_device adds a device to the passed devinfo list.
449  */
450 void
451 add_device(dev_info_t **devinfop, dev_info_t *devinfo)
452 {
453 	dev_info_t *dev;
454 
455 	if (*devinfop == NULL) {
456 		*devinfop = devinfo;
457 		return;
458 	}
459 
460 	for (dev = *devinfop; dev->next != NULL; dev = dev->next)
461 		;
462 
463 	dev->next = devinfo;
464 }
465 
466 /*
467  * OK. We totally give up. Exit back to EFI with a sensible status so
468  * it can try the next option on the list.
469  */
470 static void
471 efi_panic(EFI_STATUS s, const char *fmt, ...)
472 {
473 	va_list ap;
474 
475 	printf("panic: ");
476 	va_start(ap, fmt);
477 	vprintf(fmt, ap);
478 	va_end(ap);
479 	printf("\n");
480 
481 	BS->Exit(IH, s, 0, NULL);
482 }
483 
484 void
485 putchar(int c)
486 {
487 	CHAR16 buf[2];
488 
489 	if (c == '\n') {
490 		buf[0] = '\r';
491 		buf[1] = 0;
492 		ST->ConOut->OutputString(ST->ConOut, buf);
493 	}
494 	buf[0] = c;
495 	buf[1] = 0;
496 	ST->ConOut->OutputString(ST->ConOut, buf);
497 }
498