xref: /openbsd/sys/arch/arm64/stand/efiboot/efiboot.c (revision e8845835)
1 /*	$OpenBSD: efiboot.c,v 1.62 2024/11/12 20:49:42 tobhe Exp $	*/
2 
3 /*
4  * Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net>
5  * Copyright (c) 2016 Mark Kettenis
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/param.h>
21 #include <sys/queue.h>
22 #include <sys/stat.h>
23 #include <dev/cons.h>
24 #include <sys/disklabel.h>
25 
26 #include <efi.h>
27 #include <efiapi.h>
28 #include <efiprot.h>
29 #include <eficonsctl.h>
30 
31 #include <dev/biovar.h>
32 #include <dev/softraidvar.h>
33 
34 #include <lib/libkern/libkern.h>
35 #include <lib/libsa/softraid.h>
36 #include <stand/boot/cmd.h>
37 
38 #include "libsa.h"
39 #include "disk.h"
40 #include "softraid_arm64.h"
41 
42 #include "efidev.h"
43 #include "efiboot.h"
44 #include "efidt.h"
45 #include "fdt.h"
46 
47 EFI_SYSTEM_TABLE	*ST;
48 EFI_BOOT_SERVICES	*BS;
49 EFI_RUNTIME_SERVICES	*RS;
50 EFI_HANDLE		 IH, efi_bootdp;
51 void			*fdt_sys = NULL;
52 void			*fdt_override = NULL;
53 size_t			 fdt_override_size;
54 void			*smbios = NULL;
55 
56 EFI_PHYSICAL_ADDRESS	 heap;
57 UINTN			 heapsiz = 1 * 1024 * 1024;
58 EFI_MEMORY_DESCRIPTOR	*mmap;
59 UINTN			 mmap_key;
60 UINTN			 mmap_ndesc;
61 UINTN			 mmap_descsiz;
62 UINT32			 mmap_version;
63 
64 static EFI_GUID		 imgp_guid = LOADED_IMAGE_PROTOCOL;
65 static EFI_GUID		 blkio_guid = BLOCK_IO_PROTOCOL;
66 static EFI_GUID		 devp_guid = DEVICE_PATH_PROTOCOL;
67 static EFI_GUID		 gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
68 static EFI_GUID		 fdt_guid = FDT_TABLE_GUID;
69 static EFI_GUID		 smbios_guid = SMBIOS_TABLE_GUID;
70 static EFI_GUID		 smbios3_guid = SMBIOS3_TABLE_GUID;
71 static EFI_GUID		 dt_fixup_guid = EFI_DT_FIXUP_PROTOCOL_GUID;
72 
73 #define efi_guidcmp(_a, _b)	memcmp((_a), (_b), sizeof(EFI_GUID))
74 
75 int efi_device_path_depth(EFI_DEVICE_PATH *dp, int);
76 int efi_device_path_ncmp(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *, int);
77 static void efi_heap_init(void);
78 static void efi_memprobe_internal(void);
79 static void efi_timer_init(void);
80 static void efi_timer_cleanup(void);
81 static EFI_STATUS efi_memprobe_find(UINTN, UINTN, EFI_MEMORY_TYPE,
82     EFI_PHYSICAL_ADDRESS *);
83 void *efi_fdt(void);
84 int fdt_load_override(char *);
85 extern void smbios_init(void *);
86 
87 EFI_STATUS
88 efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
89 {
90 	extern char		*progname;
91 	EFI_LOADED_IMAGE	*imgp;
92 	EFI_DEVICE_PATH		*dp = NULL;
93 	EFI_STATUS		 status;
94 	int			 i;
95 
96 	ST = systab;
97 	BS = ST->BootServices;
98 	RS = ST->RuntimeServices;
99 	IH = image;
100 
101 	/* disable reset by watchdog after 5 minutes */
102 	BS->SetWatchdogTimer(0, 0, 0, NULL);
103 
104 	status = BS->HandleProtocol(image, &imgp_guid, (void **)&imgp);
105 	if (status == EFI_SUCCESS)
106 		status = BS->HandleProtocol(imgp->DeviceHandle, &devp_guid,
107 		    (void **)&dp);
108 	if (status == EFI_SUCCESS)
109 		efi_bootdp = dp;
110 
111 	for (i = 0; i < ST->NumberOfTableEntries; i++) {
112 		if (efi_guidcmp(&fdt_guid,
113 		    &ST->ConfigurationTable[i].VendorGuid) == 0)
114 			fdt_sys = ST->ConfigurationTable[i].VendorTable;
115 		if (efi_guidcmp(&smbios_guid,
116 		    &ST->ConfigurationTable[i].VendorGuid) == 0)
117 			smbios = ST->ConfigurationTable[i].VendorTable;
118 		if (efi_guidcmp(&smbios3_guid,
119 		    &ST->ConfigurationTable[i].VendorGuid) == 0)
120 			smbios = ST->ConfigurationTable[i].VendorTable;
121 	}
122 	fdt_init(fdt_sys);
123 
124 	progname = "BOOTAA64";
125 
126 	boot(0);
127 
128 	return (EFI_SUCCESS);
129 }
130 
131 static SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
132 static SIMPLE_INPUT_INTERFACE *conin;
133 
134 /*
135  * The device majors for these don't match the ones used by the
136  * kernel.  That's fine.  They're just used as an index into the cdevs
137  * array and never passed on to the kernel.
138  */
139 static dev_t serial = makedev(1, 0);
140 static dev_t framebuffer = makedev(2, 0);
141 
142 static char framebuffer_path[128];
143 
144 void
145 efi_cons_probe(struct consdev *cn)
146 {
147 	cn->cn_pri = CN_MIDPRI;
148 	cn->cn_dev = makedev(0, 0);
149 }
150 
151 void
152 efi_cons_init(struct consdev *cp)
153 {
154 	conin = ST->ConIn;
155 	conout = ST->ConOut;
156 }
157 
158 int
159 efi_cons_getc(dev_t dev)
160 {
161 	EFI_INPUT_KEY	 key;
162 	EFI_STATUS	 status;
163 #if 0
164 	UINTN		 dummy;
165 #endif
166 	static int	 lastchar = 0;
167 
168 	if (lastchar) {
169 		int r = lastchar;
170 		if ((dev & 0x80) == 0)
171 			lastchar = 0;
172 		return (r);
173 	}
174 
175 	status = conin->ReadKeyStroke(conin, &key);
176 	while (status == EFI_NOT_READY || key.UnicodeChar == 0) {
177 		if (dev & 0x80)
178 			return (0);
179 		/*
180 		 * XXX The implementation of WaitForEvent() in U-boot
181 		 * is broken and neverreturns.
182 		 */
183 #if 0
184 		BS->WaitForEvent(1, &conin->WaitForKey, &dummy);
185 #endif
186 		status = conin->ReadKeyStroke(conin, &key);
187 	}
188 
189 	if (dev & 0x80)
190 		lastchar = key.UnicodeChar;
191 
192 	return (key.UnicodeChar);
193 }
194 
195 void
196 efi_cons_putc(dev_t dev, int c)
197 {
198 	CHAR16	buf[2];
199 
200 	if (c == '\n')
201 		efi_cons_putc(dev, '\r');
202 
203 	buf[0] = c;
204 	buf[1] = 0;
205 
206 	conout->OutputString(conout, buf);
207 }
208 
209 void
210 efi_com_probe(struct consdev *cn)
211 {
212 	cn->cn_pri = CN_LOWPRI;
213 	cn->cn_dev = serial;
214 }
215 
216 void
217 efi_com_init(struct consdev *cn)
218 {
219 	conin = ST->ConIn;
220 	conout = ST->ConOut;
221 }
222 
223 int
224 efi_com_getc(dev_t dev)
225 {
226 	return efi_cons_getc(dev);
227 }
228 
229 void
230 efi_com_putc(dev_t dev, int c)
231 {
232 	efi_cons_putc(dev, c);
233 }
234 
235 void
236 efi_fb_probe(struct consdev *cn)
237 {
238 	cn->cn_pri = CN_LOWPRI;
239 	cn->cn_dev = framebuffer;
240 }
241 
242 void
243 efi_fb_init(struct consdev *cn)
244 {
245 	conin = ST->ConIn;
246 	conout = ST->ConOut;
247 }
248 
249 int
250 efi_fb_getc(dev_t dev)
251 {
252 	return efi_cons_getc(dev);
253 }
254 
255 void
256 efi_fb_putc(dev_t dev, int c)
257 {
258 	efi_cons_putc(dev, c);
259 }
260 
261 static void
262 efi_heap_init(void)
263 {
264 	EFI_STATUS	 status;
265 
266 	status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
267 	    EFI_SIZE_TO_PAGES(heapsiz), &heap);
268 	if (status != EFI_SUCCESS)
269 		panic("BS->AllocatePages()");
270 }
271 
272 struct disklist_lh disklist;
273 struct diskinfo *bootdev_dip;
274 
275 void
276 efi_diskprobe(void)
277 {
278 	int			 i, bootdev = 0, depth = -1;
279 	UINTN			 sz;
280 	EFI_STATUS		 status;
281 	EFI_HANDLE		*handles = NULL;
282 	EFI_BLOCK_IO		*blkio;
283 	EFI_BLOCK_IO_MEDIA	*media;
284 	struct diskinfo		*di;
285 	EFI_DEVICE_PATH		*dp;
286 
287 	TAILQ_INIT(&disklist);
288 
289 	sz = 0;
290 	status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, 0);
291 	if (status == EFI_BUFFER_TOO_SMALL) {
292 		handles = alloc(sz);
293 		status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz,
294 		    handles);
295 	}
296 	if (handles == NULL || EFI_ERROR(status))
297 		return;
298 
299 	if (efi_bootdp != NULL)
300 		depth = efi_device_path_depth(efi_bootdp, MEDIA_DEVICE_PATH);
301 
302 	/*
303 	 * U-Boot incorrectly represents devices with a single
304 	 * MEDIA_DEVICE_PATH component.  In that case include that
305 	 * component into the matching, otherwise we'll blindly select
306 	 * the first device.
307 	 */
308 	if (depth == 0)
309 		depth = 1;
310 
311 	for (i = 0; i < sz / sizeof(EFI_HANDLE); i++) {
312 		status = BS->HandleProtocol(handles[i], &blkio_guid,
313 		    (void **)&blkio);
314 		if (EFI_ERROR(status))
315 			panic("BS->HandleProtocol() returns %d", status);
316 
317 		media = blkio->Media;
318 		if (media->LogicalPartition || !media->MediaPresent)
319 			continue;
320 		di = alloc(sizeof(struct diskinfo));
321 		efid_init(di, blkio);
322 
323 		if (efi_bootdp == NULL || depth == -1 || bootdev != 0)
324 			goto next;
325 		status = BS->HandleProtocol(handles[i], &devp_guid,
326 		    (void **)&dp);
327 		if (EFI_ERROR(status))
328 			goto next;
329 		if (efi_device_path_ncmp(efi_bootdp, dp, depth) == 0) {
330 			TAILQ_INSERT_HEAD(&disklist, di, list);
331 			bootdev_dip = di;
332 			bootdev = 1;
333 			continue;
334 		}
335 next:
336 		TAILQ_INSERT_TAIL(&disklist, di, list);
337 	}
338 
339 	free(handles, sz);
340 
341 	/* Print available disks and probe for softraid. */
342 	i = 0;
343 	printf("disks:");
344 	TAILQ_FOREACH(di, &disklist, list) {
345 		printf(" sd%d%s", i, di == bootdev_dip ? "*" : "");
346 		i++;
347 	}
348 	srprobe();
349 	printf("\n");
350 }
351 
352 /*
353  * Determine the number of nodes up to, but not including, the first
354  * node of the specified type.
355  */
356 int
357 efi_device_path_depth(EFI_DEVICE_PATH *dp, int dptype)
358 {
359 	int	i;
360 
361 	for (i = 0; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp), i++) {
362 		if (DevicePathType(dp) == dptype)
363 			return (i);
364 	}
365 
366 	return (i);
367 }
368 
369 int
370 efi_device_path_ncmp(EFI_DEVICE_PATH *dpa, EFI_DEVICE_PATH *dpb, int deptn)
371 {
372 	int	 i, cmp;
373 
374 	for (i = 0; i < deptn; i++) {
375 		if (IsDevicePathEnd(dpa) || IsDevicePathEnd(dpb))
376 			return ((IsDevicePathEnd(dpa) && IsDevicePathEnd(dpb))
377 			    ? 0 : (IsDevicePathEnd(dpa))? -1 : 1);
378 		cmp = DevicePathNodeLength(dpa) - DevicePathNodeLength(dpb);
379 		if (cmp)
380 			return (cmp);
381 		cmp = memcmp(dpa, dpb, DevicePathNodeLength(dpa));
382 		if (cmp)
383 			return (cmp);
384 		dpa = NextDevicePathNode(dpa);
385 		dpb = NextDevicePathNode(dpb);
386 	}
387 
388 	return (0);
389 }
390 
391 void
392 efi_framebuffer(void)
393 {
394 	EFI_GRAPHICS_OUTPUT *gop;
395 	EFI_STATUS status;
396 	void *node, *child;
397 	uint32_t acells, scells;
398 	uint64_t base, size;
399 	uint32_t reg[4];
400 	uint32_t width, height, stride, pxsize;
401 	char *format;
402 	char *prop;
403 
404 	/*
405 	 * Don't create a "simple-framebuffer" node if we already have
406 	 * one.  Besides "/chosen", we also check under "/" since that
407 	 * is where the Raspberry Pi firmware puts it.
408 	 */
409 	node = fdt_find_node("/chosen");
410 	for (child = fdt_child_node(node); child;
411 	     child = fdt_next_node(child)) {
412 		if (!fdt_node_is_compatible(child, "simple-framebuffer"))
413 			continue;
414 		if (!fdt_node_property(child, "status", &prop) ||
415 		    strcmp(prop, "okay") == 0) {
416 			strlcpy(framebuffer_path, "/chosen/",
417 			    sizeof(framebuffer_path));
418 			strlcat(framebuffer_path, fdt_node_name(child),
419 			    sizeof(framebuffer_path));
420 			return;
421 		}
422 	}
423 	node = fdt_find_node("/");
424 	for (child = fdt_child_node(node); child;
425 	     child = fdt_next_node(child)) {
426 		if (!fdt_node_is_compatible(child, "simple-framebuffer"))
427 			continue;
428 		if (!fdt_node_property(child, "status", &prop) ||
429 		    strcmp(prop, "okay") == 0) {
430 			strlcpy(framebuffer_path, "/",
431 			    sizeof(framebuffer_path));
432 			strlcat(framebuffer_path, fdt_node_name(child),
433 			    sizeof(framebuffer_path));
434 			return;
435 		}
436 	}
437 
438 	status = BS->LocateProtocol(&gop_guid, NULL, (void **)&gop);
439 	if (status != EFI_SUCCESS)
440 		return;
441 
442 	/* Paranoia! */
443 	if (gop == NULL || gop->Mode == NULL || gop->Mode->Info == NULL)
444 		return;
445 
446 	switch (gop->Mode->Info->PixelFormat) {
447 	case PixelRedGreenBlueReserved8BitPerColor:
448 		format = "x8b8g8r8";
449 		pxsize = 4;
450 		break;
451 	case PixelBlueGreenRedReserved8BitPerColor:
452 		format = "x8r8g8b8";
453 		pxsize = 4;
454 		break;
455 	case PixelBitMask: {
456 		EFI_PIXEL_BITMASK *bm = &gop->Mode->Info->PixelInformation;
457 		if (bm->RedMask == 0xf800 &&
458 		    bm->GreenMask == 0x07e0 &&
459 		    bm->BlueMask == 0x001f) {
460 			format = "r5g6b5";
461 			pxsize = 2;
462 			break;
463 		}
464 		printf("Unsupported PixelInformation bitmasks\n");
465 		/* FALLTHROUGH */
466 	}
467 	default:
468 		printf("Unsupported PixelFormat %d, not adding "
469 		    "\"simple-framebuffer\" DT node\n",
470 		    gop->Mode->Info->PixelFormat);
471 		return;
472 	}
473 
474 	base = gop->Mode->FrameBufferBase;
475 	size = gop->Mode->FrameBufferSize;
476 	width = htobe32(gop->Mode->Info->HorizontalResolution);
477 	height = htobe32(gop->Mode->Info->VerticalResolution);
478 	stride = htobe32(gop->Mode->Info->PixelsPerScanLine * pxsize);
479 
480 	node = fdt_find_node("/");
481 	if (fdt_node_property_int(node, "#address-cells", &acells) != 1)
482 		acells = 1;
483 	if (fdt_node_property_int(node, "#size-cells", &scells) != 1)
484 		scells = 1;
485 	if (acells > 2 || scells > 2)
486 		return;
487 	if (acells >= 1)
488 		reg[0] = htobe32(base);
489 	if (acells == 2) {
490 		reg[1] = reg[0];
491 		reg[0] = htobe32(base >> 32);
492 	}
493 	if (scells >= 1)
494 		reg[acells] = htobe32(size);
495 	if (scells == 2) {
496 		reg[acells + 1] = reg[acells];
497 		reg[acells] = htobe32(size >> 32);
498 	}
499 
500 	node = fdt_find_node("/chosen");
501 	fdt_node_add_node(node, "framebuffer", &child);
502 	fdt_node_add_property(child, "status", "okay", strlen("okay") + 1);
503 	fdt_node_add_property(child, "format", format, strlen(format) + 1);
504 	fdt_node_add_property(child, "stride", &stride, 4);
505 	fdt_node_add_property(child, "height", &height, 4);
506 	fdt_node_add_property(child, "width", &width, 4);
507 	fdt_node_add_property(child, "reg", reg, (acells + scells) * 4);
508 	fdt_node_add_property(child, "compatible",
509 	    "simple-framebuffer", strlen("simple-framebuffer") + 1);
510 
511 	strlcpy(framebuffer_path, "/chosen/framebuffer",
512 	    sizeof(framebuffer_path));
513 }
514 
515 void
516 efi_console(void)
517 {
518 	void *node;
519 
520 	if (major(cn_tab->cn_dev) == major(serial)) {
521 		char *serial_path;
522 		char alias[16];
523 		int len;
524 
525 		/* Construct alias and resolve it. */
526 		snprintf(alias, sizeof(alias), "serial%d",
527 		    minor(cn_tab->cn_dev));
528 		node = fdt_find_node("/aliases");
529 		len = fdt_node_property(node, alias, &serial_path);
530 		if (len <= 0)
531 			return;
532 
533 		/* Point stdout-path at the serial node. */
534 		node = fdt_find_node("/chosen");
535 		fdt_node_add_property(node, "stdout-path",
536 		    serial_path, strlen(serial_path) + 1);
537 	} else if (major(cn_tab->cn_dev) == major(framebuffer)) {
538 		if (strlen(framebuffer_path) == 0)
539 			return;
540 
541 		/* Point stdout-path at the framebuffer node. */
542 		node = fdt_find_node("/chosen");
543 		fdt_node_add_property(node, "stdout-path",
544 		    framebuffer_path, strlen(framebuffer_path) + 1);
545 	}
546 }
547 
548 uint64_t dma_constraint[2] = { 0, -1 };
549 
550 void
551 efi_dma_constraint(void)
552 {
553 	void *node;
554 	char *prop;
555 	uint32_t *propint;
556 	uint64_t base, size;
557 	uint32_t pacells, pscells;
558 	uint32_t acells, scells;
559 	int len;
560 
561 	node = fdt_find_node("/");
562 	if (fdt_node_property_int(node, "#address-cells", &pacells) != 1)
563 		pacells = 1;
564 	if (fdt_node_property_int(node, "#size-cells", &pscells) != 1)
565 		pscells = 1;
566 	if (pacells > 2 || pscells > 2)
567 		return;
568 
569 	node = fdt_find_node("/soc");
570 	if (node != NULL) {
571 		if (fdt_node_property_int(node, "#address-cells", &acells) != 1)
572 			acells = pacells;
573 		if (fdt_node_property_int(node, "#size-cells", &scells) != 1)
574 			scells = pscells;
575 		if (acells > 2 || scells > 2)
576 			return;
577 
578 		len = fdt_node_property(node, "dma-ranges", &prop);
579 		propint = (uint32_t *)prop;
580 		if (len == (acells + pacells + scells) * sizeof(uint32_t)) {
581 			base = betoh32(propint[acells]);
582 			if (pacells == 2)
583 				base = (base << 32) |
584 				    betoh32(propint[acells + 1]);
585 			size = betoh32(propint[acells + pacells]);
586 			if (scells == 2)
587 				size = (size << 32) |
588 				    betoh32(propint[acells + pacells + 1]);
589 
590 			dma_constraint[0] = htobe64(base);
591 			dma_constraint[1] = htobe64(base + size - 1);
592 		}
593 	}
594 
595 	/*
596 	 * Some SoC's have DMA constraints that aren't explicitly
597 	 * advertised.
598 	 */
599 	node = fdt_find_node("/");
600 	if (fdt_node_is_compatible(node, "brcm,bcm2711"))
601 		dma_constraint[1] = htobe64(0x3bffffff);
602 	if (fdt_node_is_compatible(node, "rockchip,rk3566") ||
603 	    fdt_node_is_compatible(node, "rockchip,rk3568") ||
604 	    fdt_node_is_compatible(node, "rockchip,rk3588") ||
605 	    fdt_node_is_compatible(node, "rockchip,rk3588s"))
606 		dma_constraint[1] = htobe64(0xffffffff);
607 	if (fdt_node_is_compatible(node, "qcom,sc8280xp") ||
608 	    fdt_node_is_compatible(node, "qcom,x1e80100"))
609 		dma_constraint[1] = htobe64(0xffffffff);
610 
611 	/* Pass DMA constraint. */
612 	node = fdt_find_node("/chosen");
613 	fdt_node_add_property(node, "openbsd,dma-constraint",
614 	    dma_constraint, sizeof(dma_constraint));
615 }
616 
617 int acpi = 0;
618 char *bootmac = NULL;
619 
620 void *
621 efi_makebootargs(char *bootargs, int howto)
622 {
623 	struct sr_boot_volume *bv;
624 	u_char bootduid[8];
625 	u_char zero[8] = { 0 };
626 	uint64_t uefi_system_table = htobe64((uintptr_t)ST);
627 	uint32_t boothowto = htobe32(howto);
628 	EFI_PHYSICAL_ADDRESS addr;
629 	void *node, *fdt;
630 	size_t len;
631 
632 	fdt = efi_fdt();
633 	if (fdt == NULL || acpi)
634 		fdt = efi_acpi();
635 
636 	if (!fdt_get_size(fdt))
637 		return NULL;
638 
639 	len = roundup(fdt_get_size(fdt) + PAGE_SIZE, PAGE_SIZE);
640 	if (BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
641 	    EFI_SIZE_TO_PAGES(len), &addr) == EFI_SUCCESS) {
642 		memcpy((void *)addr, fdt, fdt_get_size(fdt));
643 		((struct fdt_head *)addr)->fh_size = htobe32(len);
644 		fdt = (void *)addr;
645 	}
646 
647 	if (!fdt_init(fdt))
648 		return NULL;
649 
650 	/* Create common nodes which might not exist when using mach dtb */
651 	node = fdt_find_node("/aliases");
652 	if (node == NULL)
653 		fdt_node_add_node(fdt_find_node("/"), "aliases", &node);
654 	node = fdt_find_node("/chosen");
655 	if (node == NULL)
656 		fdt_node_add_node(fdt_find_node("/"), "chosen", &node);
657 
658 	node = fdt_find_node("/chosen");
659 	len = strlen(bootargs) + 1;
660 	fdt_node_add_property(node, "bootargs", bootargs, len);
661 	fdt_node_add_property(node, "openbsd,boothowto",
662 	    &boothowto, sizeof(boothowto));
663 
664 	/* Pass DUID of the boot disk. */
665 	if (bootdev_dip) {
666 		memcpy(&bootduid, bootdev_dip->disklabel.d_uid,
667 		    sizeof(bootduid));
668 		if (memcmp(bootduid, zero, sizeof(bootduid)) != 0) {
669 			fdt_node_add_property(node, "openbsd,bootduid",
670 			    bootduid, sizeof(bootduid));
671 		}
672 
673 		if (bootdev_dip->sr_vol != NULL) {
674 			bv = bootdev_dip->sr_vol;
675 			fdt_node_add_property(node, "openbsd,sr-bootuuid",
676 			    &bv->sbv_uuid, sizeof(bv->sbv_uuid));
677 			if (bv->sbv_maskkey != NULL)
678 				fdt_node_add_property(node,
679 				    "openbsd,sr-bootkey", bv->sbv_maskkey,
680 				    SR_CRYPTO_MAXKEYBYTES);
681 		}
682 	}
683 
684 	sr_clear_keys();
685 
686 	/* Pass netboot interface address. */
687 	if (bootmac)
688 		fdt_node_add_property(node, "openbsd,bootmac", bootmac, 6);
689 
690 	/* Pass EFI system table. */
691 	fdt_node_add_property(node, "openbsd,uefi-system-table",
692 	    &uefi_system_table, sizeof(uefi_system_table));
693 
694 	/* Placeholders for EFI memory map. */
695 	fdt_node_add_property(node, "openbsd,uefi-mmap-start", zero, 8);
696 	fdt_node_add_property(node, "openbsd,uefi-mmap-size", zero, 4);
697 	fdt_node_add_property(node, "openbsd,uefi-mmap-desc-size", zero, 4);
698 	fdt_node_add_property(node, "openbsd,uefi-mmap-desc-ver", zero, 4);
699 
700 	efi_framebuffer();
701 	efi_console();
702 	efi_dma_constraint();
703 
704 	fdt_finalize();
705 
706 	return fdt;
707 }
708 
709 void
710 efi_updatefdt(void)
711 {
712 	uint64_t uefi_mmap_start = htobe64((uintptr_t)mmap);
713 	uint32_t uefi_mmap_size = htobe32(mmap_ndesc * mmap_descsiz);
714 	uint32_t uefi_mmap_desc_size = htobe32(mmap_descsiz);
715 	uint32_t uefi_mmap_desc_ver = htobe32(mmap_version);
716 	void *node;
717 
718 	node = fdt_find_node("/chosen");
719 	if (!node)
720 		return;
721 
722 	/* Pass EFI memory map. */
723 	fdt_node_set_property(node, "openbsd,uefi-mmap-start",
724 	    &uefi_mmap_start, sizeof(uefi_mmap_start));
725 	fdt_node_set_property(node, "openbsd,uefi-mmap-size",
726 	    &uefi_mmap_size, sizeof(uefi_mmap_size));
727 	fdt_node_set_property(node, "openbsd,uefi-mmap-desc-size",
728 	    &uefi_mmap_desc_size, sizeof(uefi_mmap_desc_size));
729 	fdt_node_set_property(node, "openbsd,uefi-mmap-desc-ver",
730 	    &uefi_mmap_desc_ver, sizeof(uefi_mmap_desc_ver));
731 
732 	fdt_finalize();
733 }
734 
735 u_long efi_loadaddr;
736 
737 void
738 machdep(void)
739 {
740 	EFI_PHYSICAL_ADDRESS addr;
741 
742 	cninit();
743 	efi_heap_init();
744 	smbios_init(smbios);
745 
746 	/*
747 	 * The kernel expects to be loaded into a block of memory aligned
748 	 * on a 2MB boundary.  We allocate a block of 64MB of memory, which
749 	 * gives us plenty of room for growth.
750 	 */
751 	if (efi_memprobe_find(EFI_SIZE_TO_PAGES(64 * 1024 * 1024),
752 	    0x200000, EfiLoaderCode, &addr) != EFI_SUCCESS)
753 		printf("Can't allocate memory\n");
754 	efi_loadaddr = addr;
755 
756 	efi_timer_init();
757 	efi_diskprobe();
758 	efi_pxeprobe();
759 }
760 
761 void
762 efi_cleanup(void)
763 {
764 	int		 retry;
765 	EFI_STATUS	 status;
766 
767 	efi_timer_cleanup();
768 
769 	/* retry once in case of failure */
770 	for (retry = 1; retry >= 0; retry--) {
771 		efi_memprobe_internal();	/* sync the current map */
772 		efi_updatefdt();
773 		status = BS->ExitBootServices(IH, mmap_key);
774 		if (status == EFI_SUCCESS)
775 			break;
776 		if (retry == 0)
777 			panic("ExitBootServices failed (%d)", status);
778 	}
779 }
780 
781 void
782 _rtt(void)
783 {
784 #ifdef EFI_DEBUG
785 	printf("Hit any key to reboot\n");
786 	efi_cons_getc(0);
787 #endif
788 	RS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
789 	for (;;)
790 		continue;
791 }
792 
793 /*
794  * U-Boot only implements the GetTime() Runtime Service if it has been
795  * configured with CONFIG_DM_RTC.  Most board configurations don't
796  * include that option, so we can't use it to implement our boot
797  * prompt timeout.  Instead we use timer events to simulate a clock
798  * that ticks ever second.
799  */
800 
801 EFI_EVENT timer;
802 int ticks;
803 
804 static VOID
805 efi_timer(EFI_EVENT event, VOID *context)
806 {
807 	ticks++;
808 }
809 
810 static void
811 efi_timer_init(void)
812 {
813 	EFI_STATUS status;
814 
815 	status = BS->CreateEvent(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
816 	    efi_timer, NULL, &timer);
817 	if (status == EFI_SUCCESS)
818 		status = BS->SetTimer(timer, TimerPeriodic, 10000000);
819 	if (EFI_ERROR(status))
820 		printf("Can't create timer\n");
821 }
822 
823 static void
824 efi_timer_cleanup(void)
825 {
826 	BS->CloseEvent(timer);
827 }
828 
829 time_t
830 getsecs(void)
831 {
832 	return ticks;
833 }
834 
835 /*
836  * Various device-related bits.
837  */
838 
839 void
840 devboot(dev_t dev, char *p)
841 {
842 	struct sr_boot_volume *bv;
843 	struct sr_boot_chunk *bc;
844 	struct diskinfo *dip;
845 	int sd_boot_vol = 0;
846 	int sr_boot_vol = -1;
847 	int part_type = FS_UNUSED;
848 
849 	if (bootdev_dip == NULL) {
850 		strlcpy(p, "tftp0a", 7);
851 		return;
852 	}
853 
854 	/*
855 	 * If there is no BSD disklabel on the boot device, boot from
856 	 * the ESP instead.
857 	 */
858 	if ((bootdev_dip->flags & DISKINFO_FLAG_GOODLABEL) == 0) {
859 		strlcpy(p, "esp0a", 6);
860 		return;
861 	}
862 
863 	TAILQ_FOREACH(dip, &disklist, list) {
864 		if (bootdev_dip == dip)
865 			break;
866 		sd_boot_vol++;
867 	}
868 
869 	/*
870 	 * Determine the partition type for the 'a' partition of the
871 	 * boot device.
872 	 */
873 	part_type = bootdev_dip->disklabel.d_partitions[0].p_fstype;
874 
875 	/*
876 	 * See if we booted from a disk that is a member of a bootable
877 	 * softraid volume.
878 	 */
879 	SLIST_FOREACH(bv, &sr_volumes, sbv_link) {
880 		SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link)
881 			if (bc->sbc_diskinfo == bootdev_dip)
882 				sr_boot_vol = bv->sbv_unit;
883 		if (sr_boot_vol != -1)
884 			break;
885 	}
886 
887 	if (sr_boot_vol != -1 && part_type != FS_BSDFFS) {
888 		strlcpy(p, "sr0a", 5);
889 		p[2] = '0' + sr_boot_vol;
890 		return;
891 	}
892 
893 	strlcpy(p, "sd0a", 5);
894 	p[2] = '0' + sd_boot_vol;
895 }
896 
897 const char cdevs[][4] = { "cons", "com", "fb" };
898 const int ncdevs = nitems(cdevs);
899 
900 int
901 cnspeed(dev_t dev, int sp)
902 {
903 	return 115200;
904 }
905 
906 char ttyname_buf[8];
907 
908 char *
909 ttyname(int fd)
910 {
911 	snprintf(ttyname_buf, sizeof ttyname_buf, "%s%d",
912 	    cdevs[major(cn_tab->cn_dev)], minor(cn_tab->cn_dev));
913 
914 	return ttyname_buf;
915 }
916 
917 dev_t
918 ttydev(char *name)
919 {
920 	int i, unit = -1;
921 	char *no = name + strlen(name) - 1;
922 
923 	while (no >= name && *no >= '0' && *no <= '9')
924 		unit = (unit < 0 ? 0 : (unit * 10)) + *no-- - '0';
925 	if (no < name || unit < 0)
926 		return NODEV;
927 	for (i = 0; i < ncdevs; i++)
928 		if (strncmp(name, cdevs[i], no - name + 1) == 0)
929 			return makedev(i, unit);
930 	return NODEV;
931 }
932 
933 #define MAXDEVNAME	16
934 
935 /*
936  * Parse a device spec.
937  *
938  * [A-Za-z]*[0-9]*[A-Za-z]:file
939  *    dev   uint    part
940  */
941 int
942 devparse(const char *fname, int *dev, int *unit, int *part, const char **file)
943 {
944 	const char *s;
945 
946 	*unit = 0;	/* default to wd0a */
947 	*part = 0;
948 	*dev  = 0;
949 
950 	s = strchr(fname, ':');
951 	if (s != NULL) {
952 		int devlen;
953 		int i, u, p = 0;
954 		struct devsw *dp;
955 		char devname[MAXDEVNAME];
956 
957 		devlen = s - fname;
958 		if (devlen > MAXDEVNAME)
959 			return (EINVAL);
960 
961 		/* extract device name */
962 		for (i = 0; isalpha(fname[i]) && (i < devlen); i++)
963 			devname[i] = fname[i];
964 		devname[i] = 0;
965 
966 		if (!isdigit(fname[i]))
967 			return (EUNIT);
968 
969 		/* device number */
970 		for (u = 0; isdigit(fname[i]) && (i < devlen); i++)
971 			u = u * 10 + (fname[i] - '0');
972 
973 		if (!isalpha(fname[i]))
974 			return (EPART);
975 
976 		/* partition number */
977 		if (i < devlen)
978 			p = fname[i++] - 'a';
979 
980 		if (i != devlen)
981 			return (ENXIO);
982 
983 		/* check device name */
984 		for (dp = devsw, i = 0; i < ndevs; dp++, i++) {
985 			if (dp->dv_name && !strcmp(devname, dp->dv_name))
986 				break;
987 		}
988 
989 		if (i >= ndevs)
990 			return (ENXIO);
991 
992 		*unit = u;
993 		*part = p;
994 		*dev  = i;
995 		fname = ++s;
996 	}
997 
998 	*file = fname;
999 
1000 	return (0);
1001 }
1002 
1003 int
1004 devopen(struct open_file *f, const char *fname, char **file)
1005 {
1006 	struct devsw *dp;
1007 	int dev, unit, part, error;
1008 
1009 	error = devparse(fname, &dev, &unit, &part, (const char **)file);
1010 	if (error)
1011 		return (error);
1012 
1013 	dp = &devsw[dev];
1014 	f->f_dev = dp;
1015 
1016 	if (strcmp("tftp", dp->dv_name) != 0) {
1017 		/*
1018 		 * Clear bootmac, to signal that we loaded this file from a
1019 		 * non-network device.
1020 		 */
1021 		bootmac = NULL;
1022 	}
1023 
1024 	return (*dp->dv_open)(f, unit, part);
1025 }
1026 
1027 static void
1028 efi_memprobe_internal(void)
1029 {
1030 	EFI_STATUS		 status;
1031 	UINTN			 mapkey, mmsiz, siz;
1032 	UINT32			 mmver;
1033 	EFI_MEMORY_DESCRIPTOR	*mm;
1034 	int			 n;
1035 
1036 	free(mmap, mmap_ndesc * mmap_descsiz);
1037 
1038 	siz = 0;
1039 	status = BS->GetMemoryMap(&siz, NULL, &mapkey, &mmsiz, &mmver);
1040 	if (status != EFI_BUFFER_TOO_SMALL)
1041 		panic("cannot get the size of memory map");
1042 	mm = alloc(siz);
1043 	status = BS->GetMemoryMap(&siz, mm, &mapkey, &mmsiz, &mmver);
1044 	if (status != EFI_SUCCESS)
1045 		panic("cannot get the memory map");
1046 	n = siz / mmsiz;
1047 	mmap = mm;
1048 	mmap_key = mapkey;
1049 	mmap_ndesc = n;
1050 	mmap_descsiz = mmsiz;
1051 	mmap_version = mmver;
1052 }
1053 
1054 /*
1055  * 64-bit ARMs can have a much wider memory mapping, as in somewhere
1056  * after the 32-bit region.  To cope with our alignment requirement,
1057  * use the memory table to find a place where we can fit.
1058  */
1059 static EFI_STATUS
1060 efi_memprobe_find(UINTN pages, UINTN align, EFI_MEMORY_TYPE type,
1061     EFI_PHYSICAL_ADDRESS *addr)
1062 {
1063 	EFI_MEMORY_DESCRIPTOR	*mm;
1064 	int			 i, j;
1065 
1066 	if (align < EFI_PAGE_SIZE)
1067 		return EFI_INVALID_PARAMETER;
1068 
1069 	efi_memprobe_internal();	/* sync the current map */
1070 
1071 	for (i = 0, mm = mmap; i < mmap_ndesc;
1072 	    i++, mm = NextMemoryDescriptor(mm, mmap_descsiz)) {
1073 		if (mm->Type != EfiConventionalMemory)
1074 			continue;
1075 
1076 		if (mm->NumberOfPages < pages)
1077 			continue;
1078 
1079 		for (j = 0; j < mm->NumberOfPages; j++) {
1080 			EFI_PHYSICAL_ADDRESS paddr;
1081 
1082 			if (mm->NumberOfPages - j < pages)
1083 				break;
1084 
1085 			paddr = mm->PhysicalStart + (j * EFI_PAGE_SIZE);
1086 			if (paddr & (align - 1))
1087 				continue;
1088 
1089 			if (BS->AllocatePages(AllocateAddress, type,
1090 			    pages, &paddr) == EFI_SUCCESS) {
1091 				*addr = paddr;
1092 				return EFI_SUCCESS;
1093 			}
1094 		}
1095 	}
1096 	return EFI_OUT_OF_RESOURCES;
1097 }
1098 
1099 int
1100 mdrandom(char *buf, size_t buflen)
1101 {
1102 	char *random;
1103 	void *node;
1104 	int i, len, ret = -1;
1105 
1106 	node = fdt_find_node("/chosen");
1107 	if (!node)
1108 		return -1;
1109 
1110 	len = fdt_node_property(node, "rng-seed", &random);
1111 	if (len > 0) {
1112 		for (i = 0; i < buflen; i++)
1113 			buf[i] ^= random[i % len];
1114 		ret = 0;
1115 	}
1116 
1117 	len = fdt_node_property(node, "kaslr-seed", &random);
1118 	if (len > 0) {
1119 		for (i = 0; i < buflen; i++)
1120 			buf[i] ^= random[i % len];
1121 		ret = 0;
1122 	}
1123 
1124 	return ret;
1125 }
1126 
1127 #define FW_PATH "/etc/firmware/dtb/"
1128 
1129 struct smbios_dtb {
1130 	const char *vendor;
1131 	const char *prod;
1132 	const char *dtb;
1133 } smbios_dtb[] = {
1134 	/* Keep the list below sorted by vendor */
1135 	{ "ASUS", "ASUS Vivobook S 15 S5507",
1136 	  "qcom/x1e80100-asus-vivobook-s15.dtb" },
1137 	{ "HP", "HP OmniBook X Laptop 14-fe0xxx",
1138 	  "qcom/x1e80100-hp-omnibook-x14.dtb" },
1139 	{ "LENOVO", "21BX",
1140 	  "qcom/sc8280xp-lenovo-thinkpad-x13s.dtb" },
1141 	{ "LENOVO", "21BY",
1142 	  "qcom/sc8280xp-lenovo-thinkpad-x13s.dtb" },
1143 	{ "LENOVO", "21N1",
1144 	  "qcom/x1e78100-lenovo-thinkpad-t14s.dtb" },
1145 	{ "LENOVO", "21N2",
1146 	  "qcom/x1e78100-lenovo-thinkpad-t14s.dtb" },
1147 	{ "LENOVO", "83ED",
1148 	  "qcom/x1e80100-lenovo-yoga-slim7x.dtb" },
1149 	{ "SAMSUNG", "Galaxy Book4 Edge",
1150 	  "qcom/x1e80100-samsung-galaxy-book4-edge.dtb" },
1151 };
1152 
1153 void *
1154 efi_fdt(void)
1155 {
1156 	extern char *hw_vendor, *hw_prod;
1157 	size_t vendorlen, prodlen;
1158 	char dtb[256];
1159 	int i;
1160 
1161 	/* 'mach dtb' has precedence */
1162 	if (fdt_override != NULL)
1163 		return fdt_override;
1164 
1165 	/* Return system provided one */
1166 	if (hw_vendor == NULL || hw_prod == NULL)
1167 		return fdt_sys;
1168 
1169 	for (i = 0; i < nitems(smbios_dtb); i++) {
1170 		vendorlen = strlen(smbios_dtb[i].vendor);
1171 		prodlen = strlen(smbios_dtb[i].prod);
1172 		if (strncmp(hw_vendor, smbios_dtb[i].vendor, vendorlen) == 0 &&
1173 		    strncmp(hw_prod, smbios_dtb[i].prod, prodlen) == 0) {
1174 			snprintf(dtb, sizeof(dtb), "%s%s", FW_PATH,
1175 			    smbios_dtb[i].dtb);
1176 			fdt_load_override(dtb);
1177 			/* TODO: find a better mechanism */
1178 			cnset(ttydev("fb0"));
1179 		}
1180 	}
1181 
1182 	return fdt_override ? fdt_override : fdt_sys;
1183 }
1184 
1185 int
1186 fdt_load_override(char *file)
1187 {
1188 	EFI_DT_FIXUP_PROTOCOL *dt_fixup;
1189 	EFI_PHYSICAL_ADDRESS addr;
1190 	char path[MAXPATHLEN];
1191 	EFI_STATUS status;
1192 	struct stat sb;
1193 	size_t dt_size;
1194 	UINTN sz;
1195 	int fd;
1196 
1197 	if (file == NULL && fdt_override) {
1198 		BS->FreePages((uint64_t)fdt_override,
1199 		    EFI_SIZE_TO_PAGES(fdt_override_size));
1200 		fdt_override = NULL;
1201 		fdt_init(fdt_sys);
1202 		return 0;
1203 	}
1204 
1205 	snprintf(path, sizeof(path), "%s:%s", cmd.bootdev, file);
1206 
1207 	fd = open(path, O_RDONLY);
1208 	if (fd < 0 || fstat(fd, &sb) == -1) {
1209 		printf("cannot open %s\n", path);
1210 		return 0;
1211 	}
1212 	dt_size = sb.st_size;
1213 retry:
1214 	if (efi_memprobe_find(EFI_SIZE_TO_PAGES(dt_size),
1215 	    PAGE_SIZE, EfiLoaderData, &addr) != EFI_SUCCESS) {
1216 		printf("cannot allocate memory for %s\n", path);
1217 		return 0;
1218 	}
1219 	if (read(fd, (void *)addr, sb.st_size) != sb.st_size) {
1220 		printf("cannot read from %s\n", path);
1221 		return 0;
1222 	}
1223 
1224 	status = BS->LocateProtocol(&dt_fixup_guid, NULL, (void **)&dt_fixup);
1225 	if (status == EFI_SUCCESS) {
1226 		sz = dt_size;
1227 		status = dt_fixup->Fixup(dt_fixup, (void *)addr, &sz,
1228 		    EFI_DT_APPLY_FIXUPS | EFI_DT_RESERVE_MEMORY);
1229 		if (status == EFI_BUFFER_TOO_SMALL) {
1230 			BS->FreePages(addr, EFI_SIZE_TO_PAGES(dt_size));
1231 			lseek(fd, 0, SEEK_SET);
1232 			dt_size = sz;
1233 			goto retry;
1234 		}
1235 		if (status != EFI_SUCCESS)
1236 			panic("DT fixup failed: 0x%lx", status);
1237 	}
1238 
1239 	if (!fdt_init((void *)addr)) {
1240 		printf("invalid device tree\n");
1241 		BS->FreePages(addr, EFI_SIZE_TO_PAGES(dt_size));
1242 		return 0;
1243 	}
1244 
1245 	if (fdt_override) {
1246 		BS->FreePages((uint64_t)fdt_override,
1247 		    EFI_SIZE_TO_PAGES(fdt_override_size));
1248 		fdt_override = NULL;
1249 	}
1250 
1251 	fdt_override = (void *)addr;
1252 	fdt_override_size = dt_size;
1253 	return 0;
1254 }
1255 
1256 /*
1257  * Commands
1258  */
1259 
1260 int Xacpi_efi(void);
1261 int Xdtb_efi(void);
1262 int Xexit_efi(void);
1263 int Xpoweroff_efi(void);
1264 
1265 const struct cmd_table cmd_machine[] = {
1266 	{ "acpi",	CMDT_CMD, Xacpi_efi },
1267 	{ "dtb",	CMDT_CMD, Xdtb_efi },
1268 	{ "exit",	CMDT_CMD, Xexit_efi },
1269 	{ "poweroff",	CMDT_CMD, Xpoweroff_efi },
1270 	{ NULL, 0 }
1271 };
1272 
1273 int
1274 Xacpi_efi(void)
1275 {
1276 	acpi = 1;
1277 	return (0);
1278 }
1279 
1280 int
1281 Xdtb_efi(void)
1282 {
1283 	if (cmd.argc == 1) {
1284 		fdt_load_override(NULL);
1285 		return (0);
1286 	}
1287 
1288 	if (cmd.argc != 2) {
1289 		printf("dtb file\n");
1290 		return (0);
1291 	}
1292 
1293 	return fdt_load_override(cmd.argv[1]);
1294 }
1295 
1296 int
1297 Xexit_efi(void)
1298 {
1299 	BS->Exit(IH, 0, 0, NULL);
1300 	for (;;)
1301 		continue;
1302 	return (0);
1303 }
1304 
1305 int
1306 Xpoweroff_efi(void)
1307 {
1308 	RS->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
1309 	return (0);
1310 }
1311