xref: /openbsd-src/sys/arch/riscv64/stand/efiboot/efiboot.c (revision 3b1a37cb83ce5be75c96a136324d97cfeb2a0888)
1 /*	$OpenBSD: efiboot.c,v 1.11 2024/06/23 13:11:51 kettenis 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_riscv64.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 
55 EFI_PHYSICAL_ADDRESS	 heap;
56 UINTN			 heapsiz = 1 * 1024 * 1024;
57 EFI_MEMORY_DESCRIPTOR	*mmap;
58 UINTN			 mmap_key;
59 UINTN			 mmap_ndesc;
60 UINTN			 mmap_descsiz;
61 UINT32			 mmap_version;
62 
63 static EFI_GUID		 imgp_guid = LOADED_IMAGE_PROTOCOL;
64 static EFI_GUID		 blkio_guid = BLOCK_IO_PROTOCOL;
65 static EFI_GUID		 devp_guid = DEVICE_PATH_PROTOCOL;
66 static EFI_GUID		 gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
67 static EFI_GUID		 fdt_guid = FDT_TABLE_GUID;
68 static EFI_GUID		 dt_fixup_guid = EFI_DT_FIXUP_PROTOCOL_GUID;
69 
70 #define efi_guidcmp(_a, _b)	memcmp((_a), (_b), sizeof(EFI_GUID))
71 
72 int efi_device_path_depth(EFI_DEVICE_PATH *dp, int);
73 int efi_device_path_ncmp(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *, int);
74 static void efi_heap_init(void);
75 static void efi_memprobe_internal(void);
76 static void efi_timer_init(void);
77 static void efi_timer_cleanup(void);
78 static EFI_STATUS efi_memprobe_find(UINTN, UINTN, EFI_PHYSICAL_ADDRESS *);
79 void *efi_fdt(void);
80 int fdt_load_override(char *);
81 
82 EFI_STATUS
efi_main(EFI_HANDLE image,EFI_SYSTEM_TABLE * systab)83 efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
84 {
85 	extern char		*progname;
86 	EFI_LOADED_IMAGE	*imgp;
87 	EFI_DEVICE_PATH		*dp = NULL;
88 	EFI_STATUS		 status;
89 	int			 i;
90 
91 	ST = systab;
92 	BS = ST->BootServices;
93 	RS = ST->RuntimeServices;
94 	IH = image;
95 
96 	/* disable reset by watchdog after 5 minutes */
97 	BS->SetWatchdogTimer(0, 0, 0, NULL);
98 
99 	status = BS->HandleProtocol(image, &imgp_guid, (void **)&imgp);
100 	if (status == EFI_SUCCESS)
101 		status = BS->HandleProtocol(imgp->DeviceHandle, &devp_guid,
102 		    (void **)&dp);
103 	if (status == EFI_SUCCESS)
104 		efi_bootdp = dp;
105 
106 	for (i = 0; i < ST->NumberOfTableEntries; i++) {
107 		if (efi_guidcmp(&fdt_guid,
108 		    &ST->ConfigurationTable[i].VendorGuid) == 0)
109 			fdt_sys = ST->ConfigurationTable[i].VendorTable;
110 	}
111 	fdt_init(fdt_sys);
112 
113 	progname = "BOOTRISCV64";
114 
115 	boot(0);
116 
117 	return (EFI_SUCCESS);
118 }
119 
120 static SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
121 static SIMPLE_INPUT_INTERFACE *conin;
122 
123 /*
124  * The device majors for these don't match the ones used by the
125  * kernel.  That's fine.  They're just used as an index into the cdevs
126  * array and never passed on to the kernel.
127  */
128 static dev_t serial = makedev(0, 0);
129 static dev_t framebuffer = makedev(1, 0);
130 
131 static char framebuffer_path[128];
132 
133 void
efi_cons_probe(struct consdev * cn)134 efi_cons_probe(struct consdev *cn)
135 {
136 	cn->cn_pri = CN_MIDPRI;
137 	cn->cn_dev = serial;
138 }
139 
140 void
efi_cons_init(struct consdev * cp)141 efi_cons_init(struct consdev *cp)
142 {
143 	conin = ST->ConIn;
144 	conout = ST->ConOut;
145 }
146 
147 int
efi_cons_getc(dev_t dev)148 efi_cons_getc(dev_t dev)
149 {
150 	EFI_INPUT_KEY	 key;
151 	EFI_STATUS	 status;
152 #if 0
153 	UINTN		 dummy;
154 #endif
155 	static int	 lastchar = 0;
156 
157 	if (lastchar) {
158 		int r = lastchar;
159 		if ((dev & 0x80) == 0)
160 			lastchar = 0;
161 		return (r);
162 	}
163 
164 	status = conin->ReadKeyStroke(conin, &key);
165 	while (status == EFI_NOT_READY || key.UnicodeChar == 0) {
166 		if (dev & 0x80)
167 			return (0);
168 		/*
169 		 * XXX The implementation of WaitForEvent() in U-boot
170 		 * is broken and neverreturns.
171 		 */
172 #if 0
173 		BS->WaitForEvent(1, &conin->WaitForKey, &dummy);
174 #endif
175 		status = conin->ReadKeyStroke(conin, &key);
176 	}
177 
178 	if (dev & 0x80)
179 		lastchar = key.UnicodeChar;
180 
181 	return (key.UnicodeChar);
182 }
183 
184 void
efi_cons_putc(dev_t dev,int c)185 efi_cons_putc(dev_t dev, int c)
186 {
187 	CHAR16	buf[2];
188 
189 	if (c == '\n')
190 		efi_cons_putc(dev, '\r');
191 
192 	buf[0] = c;
193 	buf[1] = 0;
194 
195 	conout->OutputString(conout, buf);
196 }
197 
198 void
efi_fb_probe(struct consdev * cn)199 efi_fb_probe(struct consdev *cn)
200 {
201 	cn->cn_pri = CN_LOWPRI;
202 	cn->cn_dev = framebuffer;
203 }
204 
205 void
efi_fb_init(struct consdev * cn)206 efi_fb_init(struct consdev *cn)
207 {
208 	conin = ST->ConIn;
209 	conout = ST->ConOut;
210 }
211 
212 int
efi_fb_getc(dev_t dev)213 efi_fb_getc(dev_t dev)
214 {
215 	return efi_cons_getc(dev);
216 }
217 
218 void
efi_fb_putc(dev_t dev,int c)219 efi_fb_putc(dev_t dev, int c)
220 {
221 	efi_cons_putc(dev, c);
222 }
223 
224 static void
efi_heap_init(void)225 efi_heap_init(void)
226 {
227 	EFI_STATUS	 status;
228 
229 	status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
230 	    EFI_SIZE_TO_PAGES(heapsiz), &heap);
231 	if (status != EFI_SUCCESS)
232 		panic("BS->AllocatePages()");
233 }
234 
235 struct disklist_lh disklist;
236 struct diskinfo *bootdev_dip;
237 
238 void
efi_diskprobe(void)239 efi_diskprobe(void)
240 {
241 	int			 i, bootdev = 0, depth = -1;
242 	UINTN			 sz;
243 	EFI_STATUS		 status;
244 	EFI_HANDLE		*handles = NULL;
245 	EFI_BLOCK_IO		*blkio;
246 	EFI_BLOCK_IO_MEDIA	*media;
247 	struct diskinfo		*di;
248 	EFI_DEVICE_PATH		*dp;
249 
250 	TAILQ_INIT(&disklist);
251 
252 	sz = 0;
253 	status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, 0);
254 	if (status == EFI_BUFFER_TOO_SMALL) {
255 		handles = alloc(sz);
256 		status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz,
257 		    handles);
258 	}
259 	if (handles == NULL || EFI_ERROR(status))
260 		return;
261 
262 	if (efi_bootdp != NULL)
263 		depth = efi_device_path_depth(efi_bootdp, MEDIA_DEVICE_PATH);
264 
265 	/*
266 	 * U-Boot incorrectly represents devices with a single
267 	 * MEDIA_DEVICE_PATH component.  In that case include that
268 	 * component into the matching, otherwise we'll blindly select
269 	 * the first device.
270 	 */
271 	if (depth == 0)
272 		depth = 1;
273 
274 	for (i = 0; i < sz / sizeof(EFI_HANDLE); i++) {
275 		status = BS->HandleProtocol(handles[i], &blkio_guid,
276 		    (void **)&blkio);
277 		if (EFI_ERROR(status))
278 			panic("BS->HandleProtocol() returns %d", status);
279 
280 		media = blkio->Media;
281 		if (media->LogicalPartition || !media->MediaPresent)
282 			continue;
283 		di = alloc(sizeof(struct diskinfo));
284 		efid_init(di, blkio);
285 
286 		if (efi_bootdp == NULL || depth == -1 || bootdev != 0)
287 			goto next;
288 		status = BS->HandleProtocol(handles[i], &devp_guid,
289 		    (void **)&dp);
290 		if (EFI_ERROR(status))
291 			goto next;
292 		if (efi_device_path_ncmp(efi_bootdp, dp, depth) == 0) {
293 			TAILQ_INSERT_HEAD(&disklist, di, list);
294 			bootdev_dip = di;
295 			bootdev = 1;
296 			continue;
297 		}
298 next:
299 		TAILQ_INSERT_TAIL(&disklist, di, list);
300 	}
301 
302 	free(handles, sz);
303 
304 	/* Print available disks and probe for softraid. */
305 	i = 0;
306 	printf("disks:");
307 	TAILQ_FOREACH(di, &disklist, list) {
308 		printf(" sd%d%s", i, di == bootdev_dip ? "*" : "");
309 		i++;
310 	}
311 	srprobe();
312 	printf("\n");
313 }
314 
315 /*
316  * Determine the number of nodes up to, but not including, the first
317  * node of the specified type.
318  */
319 int
efi_device_path_depth(EFI_DEVICE_PATH * dp,int dptype)320 efi_device_path_depth(EFI_DEVICE_PATH *dp, int dptype)
321 {
322 	int	i;
323 
324 	for (i = 0; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp), i++) {
325 		if (DevicePathType(dp) == dptype)
326 			return (i);
327 	}
328 
329 	return (i);
330 }
331 
332 int
efi_device_path_ncmp(EFI_DEVICE_PATH * dpa,EFI_DEVICE_PATH * dpb,int deptn)333 efi_device_path_ncmp(EFI_DEVICE_PATH *dpa, EFI_DEVICE_PATH *dpb, int deptn)
334 {
335 	int	 i, cmp;
336 
337 	for (i = 0; i < deptn; i++) {
338 		if (IsDevicePathEnd(dpa) || IsDevicePathEnd(dpb))
339 			return ((IsDevicePathEnd(dpa) && IsDevicePathEnd(dpb))
340 			    ? 0 : (IsDevicePathEnd(dpa))? -1 : 1);
341 		cmp = DevicePathNodeLength(dpa) - DevicePathNodeLength(dpb);
342 		if (cmp)
343 			return (cmp);
344 		cmp = memcmp(dpa, dpb, DevicePathNodeLength(dpa));
345 		if (cmp)
346 			return (cmp);
347 		dpa = NextDevicePathNode(dpa);
348 		dpb = NextDevicePathNode(dpb);
349 	}
350 
351 	return (0);
352 }
353 
354 void
efi_framebuffer(void)355 efi_framebuffer(void)
356 {
357 	EFI_GRAPHICS_OUTPUT *gop;
358 	EFI_STATUS status;
359 	void *node, *child;
360 	uint32_t acells, scells;
361 	uint64_t base, size;
362 	uint32_t reg[4];
363 	uint32_t width, height, stride;
364 	char *format;
365 	char *prop;
366 
367 	/*
368 	 * Don't create a "simple-framebuffer" node if we already have
369 	 * one.  Besides "/chosen", we also check under "/" since that
370 	 * is where the Raspberry Pi firmware puts it.
371 	 */
372 	node = fdt_find_node("/chosen");
373 	for (child = fdt_child_node(node); child;
374 	     child = fdt_next_node(child)) {
375 		if (!fdt_node_is_compatible(child, "simple-framebuffer"))
376 			continue;
377 		if (!fdt_node_property(child, "status", &prop) ||
378 		    strcmp(prop, "okay") == 0) {
379 			strlcpy(framebuffer_path, "/chosen/",
380 			    sizeof(framebuffer_path));
381 			strlcat(framebuffer_path, fdt_node_name(child),
382 			    sizeof(framebuffer_path));
383 			return;
384 		}
385 	}
386 	node = fdt_find_node("/");
387 	for (child = fdt_child_node(node); child;
388 	     child = fdt_next_node(child)) {
389 		if (!fdt_node_is_compatible(child, "simple-framebuffer"))
390 			continue;
391 		if (!fdt_node_property(child, "status", &prop) ||
392 		    strcmp(prop, "okay") == 0) {
393 			strlcpy(framebuffer_path, "/",
394 			    sizeof(framebuffer_path));
395 			strlcat(framebuffer_path, fdt_node_name(child),
396 			    sizeof(framebuffer_path));
397 			return;
398 		}
399 	}
400 
401 	status = BS->LocateProtocol(&gop_guid, NULL, (void **)&gop);
402 	if (status != EFI_SUCCESS)
403 		return;
404 
405 	/* Paranoia! */
406 	if (gop == NULL || gop->Mode == NULL || gop->Mode->Info == NULL)
407 		return;
408 
409 	/* We only support 32-bit pixel modes for now. */
410 	switch (gop->Mode->Info->PixelFormat) {
411 	case PixelRedGreenBlueReserved8BitPerColor:
412 		format = "x8b8g8r8";
413 		break;
414 	case PixelBlueGreenRedReserved8BitPerColor:
415 		format = "x8r8g8b8";
416 		break;
417 	default:
418 		return;
419 	}
420 
421 	base = gop->Mode->FrameBufferBase;
422 	size = gop->Mode->FrameBufferSize;
423 	width = htobe32(gop->Mode->Info->HorizontalResolution);
424 	height = htobe32(gop->Mode->Info->VerticalResolution);
425 	stride = htobe32(gop->Mode->Info->PixelsPerScanLine * 4);
426 
427 	node = fdt_find_node("/");
428 	if (fdt_node_property_int(node, "#address-cells", &acells) != 1)
429 		acells = 1;
430 	if (fdt_node_property_int(node, "#size-cells", &scells) != 1)
431 		scells = 1;
432 	if (acells > 2 || scells > 2)
433 		return;
434 	if (acells >= 1)
435 		reg[0] = htobe32(base);
436 	if (acells == 2) {
437 		reg[1] = reg[0];
438 		reg[0] = htobe32(base >> 32);
439 	}
440 	if (scells >= 1)
441 		reg[acells] = htobe32(size);
442 	if (scells == 2) {
443 		reg[acells + 1] = reg[acells];
444 		reg[acells] = htobe32(size >> 32);
445 	}
446 
447 	node = fdt_find_node("/chosen");
448 	fdt_node_add_node(node, "framebuffer", &child);
449 	fdt_node_add_property(child, "status", "okay", strlen("okay") + 1);
450 	fdt_node_add_property(child, "format", format, strlen(format) + 1);
451 	fdt_node_add_property(child, "stride", &stride, 4);
452 	fdt_node_add_property(child, "height", &height, 4);
453 	fdt_node_add_property(child, "width", &width, 4);
454 	fdt_node_add_property(child, "reg", reg, (acells + scells) * 4);
455 	fdt_node_add_property(child, "compatible",
456 	    "simple-framebuffer", strlen("simple-framebuffer") + 1);
457 
458 	strlcpy(framebuffer_path, "/chosen/framebuffer",
459 	    sizeof(framebuffer_path));
460 }
461 
462 void
efi_console(void)463 efi_console(void)
464 {
465 	void *node;
466 
467 	if (cn_tab->cn_dev != framebuffer)
468 		return;
469 
470 	if (strlen(framebuffer_path) == 0)
471 		return;
472 
473 	/* Point stdout-path at the framebuffer node. */
474 	node = fdt_find_node("/chosen");
475 	fdt_node_add_property(node, "stdout-path",
476 	    framebuffer_path, strlen(framebuffer_path) + 1);
477 }
478 
479 uint64_t dma_constraint[2] = { 0, -1 };
480 
481 void
efi_dma_constraint(void)482 efi_dma_constraint(void)
483 {
484 	void *node;
485 
486 	/* StarFive JH71x0 has peripherals that only support 32-bit DMA. */
487 	node = fdt_find_node("/");
488 	if (fdt_node_is_compatible(node, "starfive,jh7100") ||
489 	    fdt_node_is_compatible(node, "starfive,jh7110"))
490 		dma_constraint[1] = htobe64(0xffffffff);
491 
492 	/* Pass DMA constraint. */
493 	node = fdt_find_node("/chosen");
494 	fdt_node_add_property(node, "openbsd,dma-constraint",
495 	    dma_constraint, sizeof(dma_constraint));
496 }
497 
498 char *bootmac = NULL;
499 
500 void *
efi_makebootargs(char * bootargs,int howto)501 efi_makebootargs(char *bootargs, int howto)
502 {
503 	struct sr_boot_volume *bv;
504 	u_char bootduid[8];
505 	u_char zero[8] = { 0 };
506 	uint64_t uefi_system_table = htobe64((uintptr_t)ST);
507 	uint32_t boothowto = htobe32(howto);
508 	int32_t hartid;
509 	EFI_PHYSICAL_ADDRESS addr;
510 	void *node, *fdt;
511 	size_t len;
512 
513 	fdt = efi_fdt();
514 	if (fdt == NULL)
515 		return NULL;
516 
517 	if (!fdt_get_size(fdt))
518 		return NULL;
519 
520 	len = roundup(fdt_get_size(fdt) + PAGE_SIZE, PAGE_SIZE);
521 	if (BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
522 	    EFI_SIZE_TO_PAGES(len), &addr) == EFI_SUCCESS) {
523 		memcpy((void *)addr, fdt, fdt_get_size(fdt));
524 		((struct fdt_head *)addr)->fh_size = htobe32(len);
525 		fdt = (void *)addr;
526 	}
527 
528 	if (!fdt_init(fdt))
529 		return NULL;
530 
531 	/* Create common nodes which might not exist when using mach dtb */
532 	node = fdt_find_node("/aliases");
533 	if (node == NULL)
534 		fdt_node_add_node(fdt_find_node("/"), "aliases", &node);
535 	node = fdt_find_node("/chosen");
536 	if (node == NULL)
537 		fdt_node_add_node(fdt_find_node("/"), "chosen", &node);
538 
539 	node = fdt_find_node("/chosen");
540 	hartid = efi_get_boot_hart_id();
541 	if (hartid >= 0) {
542 		hartid = htobe32(hartid);
543 		fdt_node_add_property(node, "boot-hartid", &hartid, 4);
544 	}
545 
546 	len = strlen(bootargs) + 1;
547 	fdt_node_add_property(node, "bootargs", bootargs, len);
548 	fdt_node_add_property(node, "openbsd,boothowto",
549 	    &boothowto, sizeof(boothowto));
550 
551 	/* Pass DUID of the boot disk. */
552 	if (bootdev_dip) {
553 		memcpy(&bootduid, bootdev_dip->disklabel.d_uid,
554 		    sizeof(bootduid));
555 		if (memcmp(bootduid, zero, sizeof(bootduid)) != 0) {
556 			fdt_node_add_property(node, "openbsd,bootduid",
557 			    bootduid, sizeof(bootduid));
558 		}
559 
560 		if (bootdev_dip->sr_vol != NULL) {
561 			bv = bootdev_dip->sr_vol;
562 			fdt_node_add_property(node, "openbsd,sr-bootuuid",
563 			    &bv->sbv_uuid, sizeof(bv->sbv_uuid));
564 			if (bv->sbv_maskkey != NULL)
565 				fdt_node_add_property(node,
566 				    "openbsd,sr-bootkey", bv->sbv_maskkey,
567 				    SR_CRYPTO_MAXKEYBYTES);
568 		}
569 	}
570 
571 	sr_clear_keys();
572 
573 	/* Pass netboot interface address. */
574 	if (bootmac)
575 		fdt_node_add_property(node, "openbsd,bootmac", bootmac, 6);
576 
577 	/* Pass EFI system table. */
578 	fdt_node_add_property(node, "openbsd,uefi-system-table",
579 	    &uefi_system_table, sizeof(uefi_system_table));
580 
581 	/* Placeholders for EFI memory map. */
582 	fdt_node_add_property(node, "openbsd,uefi-mmap-start", zero, 8);
583 	fdt_node_add_property(node, "openbsd,uefi-mmap-size", zero, 4);
584 	fdt_node_add_property(node, "openbsd,uefi-mmap-desc-size", zero, 4);
585 	fdt_node_add_property(node, "openbsd,uefi-mmap-desc-ver", zero, 4);
586 
587 	efi_framebuffer();
588 	efi_console();
589 	efi_dma_constraint();
590 
591 	fdt_finalize();
592 
593 	return fdt;
594 }
595 
596 void
efi_updatefdt(void)597 efi_updatefdt(void)
598 {
599 	uint64_t uefi_mmap_start = htobe64((uintptr_t)mmap);
600 	uint32_t uefi_mmap_size = htobe32(mmap_ndesc * mmap_descsiz);
601 	uint32_t uefi_mmap_desc_size = htobe32(mmap_descsiz);
602 	uint32_t uefi_mmap_desc_ver = htobe32(mmap_version);
603 	void *node;
604 
605 	node = fdt_find_node("/chosen");
606 	if (!node)
607 		return;
608 
609 	/* Pass EFI memory map. */
610 	fdt_node_set_property(node, "openbsd,uefi-mmap-start",
611 	    &uefi_mmap_start, sizeof(uefi_mmap_start));
612 	fdt_node_set_property(node, "openbsd,uefi-mmap-size",
613 	    &uefi_mmap_size, sizeof(uefi_mmap_size));
614 	fdt_node_set_property(node, "openbsd,uefi-mmap-desc-size",
615 	    &uefi_mmap_desc_size, sizeof(uefi_mmap_desc_size));
616 	fdt_node_set_property(node, "openbsd,uefi-mmap-desc-ver",
617 	    &uefi_mmap_desc_ver, sizeof(uefi_mmap_desc_ver));
618 
619 	fdt_finalize();
620 }
621 
622 u_long efi_loadaddr;
623 
624 void
machdep(void)625 machdep(void)
626 {
627 	EFI_PHYSICAL_ADDRESS addr;
628 
629 	cninit();
630 	efi_heap_init();
631 
632 	/*
633 	 * The kernel expects to be loaded into a block of memory aligned
634 	 * on a 2MB boundary.  We allocate a block of 64MB of memory, which
635 	 * gives us plenty of room for growth.
636 	 */
637 	if (efi_memprobe_find(EFI_SIZE_TO_PAGES(64 * 1024 * 1024),
638 	    0x200000, &addr) != EFI_SUCCESS)
639 		printf("Can't allocate memory\n");
640 	efi_loadaddr = addr;
641 
642 	efi_timer_init();
643 	efi_diskprobe();
644 	efi_pxeprobe();
645 }
646 
647 void
efi_cleanup(void)648 efi_cleanup(void)
649 {
650 	int		 retry;
651 	EFI_STATUS	 status;
652 
653 	efi_timer_cleanup();
654 
655 	/* retry once in case of failure */
656 	for (retry = 1; retry >= 0; retry--) {
657 		efi_memprobe_internal();	/* sync the current map */
658 		efi_updatefdt();
659 		status = BS->ExitBootServices(IH, mmap_key);
660 		if (status == EFI_SUCCESS)
661 			break;
662 		if (retry == 0)
663 			panic("ExitBootServices failed (%d)", status);
664 	}
665 }
666 
667 void
_rtt(void)668 _rtt(void)
669 {
670 #ifdef EFI_DEBUG
671 	printf("Hit any key to reboot\n");
672 	efi_cons_getc(0);
673 #endif
674 	RS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
675 	for (;;)
676 		continue;
677 }
678 
679 /*
680  * U-Boot only implements the GetTime() Runtime Service if it has been
681  * configured with CONFIG_DM_RTC.  Most board configurations don't
682  * include that option, so we can't use it to implement our boot
683  * prompt timeout.  Instead we use timer events to simulate a clock
684  * that ticks ever second.
685  */
686 
687 EFI_EVENT timer;
688 int ticks;
689 
690 static VOID
efi_timer(EFI_EVENT event,VOID * context)691 efi_timer(EFI_EVENT event, VOID *context)
692 {
693 	ticks++;
694 }
695 
696 static void
efi_timer_init(void)697 efi_timer_init(void)
698 {
699 	EFI_STATUS status;
700 
701 	status = BS->CreateEvent(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
702 	    efi_timer, NULL, &timer);
703 	if (status == EFI_SUCCESS)
704 		status = BS->SetTimer(timer, TimerPeriodic, 10000000);
705 	if (EFI_ERROR(status))
706 		printf("Can't create timer\n");
707 }
708 
709 static void
efi_timer_cleanup(void)710 efi_timer_cleanup(void)
711 {
712 	BS->CloseEvent(timer);
713 }
714 
715 time_t
getsecs(void)716 getsecs(void)
717 {
718 	return ticks;
719 }
720 
721 /*
722  * Various device-related bits.
723  */
724 
725 void
devboot(dev_t dev,char * p)726 devboot(dev_t dev, char *p)
727 {
728 	struct sr_boot_volume *bv;
729 	struct sr_boot_chunk *bc;
730 	struct diskinfo *dip;
731 	int sd_boot_vol = 0;
732 	int sr_boot_vol = -1;
733 	int part_type = FS_UNUSED;
734 
735 	if (bootdev_dip == NULL) {
736 		strlcpy(p, "tftp0a", 7);
737 		return;
738 	}
739 
740 	TAILQ_FOREACH(dip, &disklist, list) {
741 		if (bootdev_dip == dip)
742 			break;
743 		sd_boot_vol++;
744 	}
745 
746 	/*
747 	 * Determine the partition type for the 'a' partition of the
748 	 * boot device.
749 	 */
750 	if ((bootdev_dip->flags & DISKINFO_FLAG_GOODLABEL) != 0)
751 		part_type = bootdev_dip->disklabel.d_partitions[0].p_fstype;
752 
753 	/*
754 	 * See if we booted from a disk that is a member of a bootable
755 	 * softraid volume.
756 	 */
757 	SLIST_FOREACH(bv, &sr_volumes, sbv_link) {
758 		SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link)
759 			if (bc->sbc_diskinfo == bootdev_dip)
760 				sr_boot_vol = bv->sbv_unit;
761 		if (sr_boot_vol != -1)
762 			break;
763 	}
764 
765 	if (sr_boot_vol != -1 && part_type != FS_BSDFFS) {
766 		strlcpy(p, "sr0a", 5);
767 		p[2] = '0' + sr_boot_vol;
768 		return;
769 	}
770 
771 	strlcpy(p, "sd0a", 5);
772 	p[2] = '0' + sd_boot_vol;
773 }
774 
775 const char cdevs[][4] = { "com", "fb" };
776 const int ncdevs = nitems(cdevs);
777 
778 int
cnspeed(dev_t dev,int sp)779 cnspeed(dev_t dev, int sp)
780 {
781 	return 115200;
782 }
783 
784 char ttyname_buf[8];
785 
786 char *
ttyname(int fd)787 ttyname(int fd)
788 {
789 	snprintf(ttyname_buf, sizeof ttyname_buf, "%s%d",
790 	    cdevs[major(cn_tab->cn_dev)], minor(cn_tab->cn_dev));
791 
792 	return ttyname_buf;
793 }
794 
795 dev_t
ttydev(char * name)796 ttydev(char *name)
797 {
798 	int i, unit = -1;
799 	char *no = name + strlen(name) - 1;
800 
801 	while (no >= name && *no >= '0' && *no <= '9')
802 		unit = (unit < 0 ? 0 : (unit * 10)) + *no-- - '0';
803 	if (no < name || unit < 0)
804 		return NODEV;
805 	for (i = 0; i < ncdevs; i++)
806 		if (strncmp(name, cdevs[i], no - name + 1) == 0)
807 			return makedev(i, unit);
808 	return NODEV;
809 }
810 
811 #define MAXDEVNAME	16
812 
813 /*
814  * Parse a device spec.
815  *
816  * [A-Za-z]*[0-9]*[A-Za-z]:file
817  *    dev   uint    part
818  */
819 int
devparse(const char * fname,int * dev,int * unit,int * part,const char ** file)820 devparse(const char *fname, int *dev, int *unit, int *part, const char **file)
821 {
822 	const char *s;
823 
824 	*unit = 0;	/* default to wd0a */
825 	*part = 0;
826 	*dev  = 0;
827 
828 	s = strchr(fname, ':');
829 	if (s != NULL) {
830 		int devlen;
831 		int i, u, p = 0;
832 		struct devsw *dp;
833 		char devname[MAXDEVNAME];
834 
835 		devlen = s - fname;
836 		if (devlen > MAXDEVNAME)
837 			return (EINVAL);
838 
839 		/* extract device name */
840 		for (i = 0; isalpha(fname[i]) && (i < devlen); i++)
841 			devname[i] = fname[i];
842 		devname[i] = 0;
843 
844 		if (!isdigit(fname[i]))
845 			return (EUNIT);
846 
847 		/* device number */
848 		for (u = 0; isdigit(fname[i]) && (i < devlen); i++)
849 			u = u * 10 + (fname[i] - '0');
850 
851 		if (!isalpha(fname[i]))
852 			return (EPART);
853 
854 		/* partition number */
855 		if (i < devlen)
856 			p = fname[i++] - 'a';
857 
858 		if (i != devlen)
859 			return (ENXIO);
860 
861 		/* check device name */
862 		for (dp = devsw, i = 0; i < ndevs; dp++, i++) {
863 			if (dp->dv_name && !strcmp(devname, dp->dv_name))
864 				break;
865 		}
866 
867 		if (i >= ndevs)
868 			return (ENXIO);
869 
870 		*unit = u;
871 		*part = p;
872 		*dev  = i;
873 		fname = ++s;
874 	}
875 
876 	*file = fname;
877 
878 	return (0);
879 }
880 
881 int
devopen(struct open_file * f,const char * fname,char ** file)882 devopen(struct open_file *f, const char *fname, char **file)
883 {
884 	struct devsw *dp;
885 	int dev, unit, part, error;
886 
887 	error = devparse(fname, &dev, &unit, &part, (const char **)file);
888 	if (error)
889 		return (error);
890 
891 	dp = &devsw[dev];
892 	f->f_dev = dp;
893 
894 	if (strcmp("tftp", dp->dv_name) != 0) {
895 		/*
896 		 * Clear bootmac, to signal that we loaded this file from a
897 		 * non-network device.
898 		 */
899 		bootmac = NULL;
900 	}
901 
902 	return (*dp->dv_open)(f, unit, part);
903 }
904 
905 static void
efi_memprobe_internal(void)906 efi_memprobe_internal(void)
907 {
908 	EFI_STATUS		 status;
909 	UINTN			 mapkey, mmsiz, siz;
910 	UINT32			 mmver;
911 	EFI_MEMORY_DESCRIPTOR	*mm;
912 	int			 n;
913 
914 	free(mmap, mmap_ndesc * mmap_descsiz);
915 
916 	siz = 0;
917 	status = BS->GetMemoryMap(&siz, NULL, &mapkey, &mmsiz, &mmver);
918 	if (status != EFI_BUFFER_TOO_SMALL)
919 		panic("cannot get the size of memory map");
920 	mm = alloc(siz);
921 	status = BS->GetMemoryMap(&siz, mm, &mapkey, &mmsiz, &mmver);
922 	if (status != EFI_SUCCESS)
923 		panic("cannot get the memory map");
924 	n = siz / mmsiz;
925 	mmap = mm;
926 	mmap_key = mapkey;
927 	mmap_ndesc = n;
928 	mmap_descsiz = mmsiz;
929 	mmap_version = mmver;
930 }
931 
932 /*
933  * 64-bit ARMs can have a much wider memory mapping, as in somewhere
934  * after the 32-bit region.  To cope with our alignment requirement,
935  * use the memory table to find a place where we can fit.
936  */
937 static EFI_STATUS
efi_memprobe_find(UINTN pages,UINTN align,EFI_PHYSICAL_ADDRESS * addr)938 efi_memprobe_find(UINTN pages, UINTN align, EFI_PHYSICAL_ADDRESS *addr)
939 {
940 	EFI_MEMORY_DESCRIPTOR	*mm;
941 	int			 i, j;
942 
943 	if (align < EFI_PAGE_SIZE)
944 		return EFI_INVALID_PARAMETER;
945 
946 	efi_memprobe_internal();	/* sync the current map */
947 
948 	for (i = 0, mm = mmap; i < mmap_ndesc;
949 	    i++, mm = NextMemoryDescriptor(mm, mmap_descsiz)) {
950 		if (mm->Type != EfiConventionalMemory)
951 			continue;
952 
953 		if (mm->NumberOfPages < pages)
954 			continue;
955 
956 		for (j = 0; j < mm->NumberOfPages; j++) {
957 			EFI_PHYSICAL_ADDRESS paddr;
958 
959 			if (mm->NumberOfPages - j < pages)
960 				break;
961 
962 			paddr = mm->PhysicalStart + (j * EFI_PAGE_SIZE);
963 			if (paddr & (align - 1))
964 				continue;
965 
966 			if (BS->AllocatePages(AllocateAddress, EfiLoaderData,
967 			    pages, &paddr) == EFI_SUCCESS) {
968 				*addr = paddr;
969 				return EFI_SUCCESS;
970 			}
971 		}
972 	}
973 	return EFI_OUT_OF_RESOURCES;
974 }
975 
976 void *
efi_fdt(void)977 efi_fdt(void)
978 {
979 	/* 'mach dtb' has precedence */
980 	if (fdt_override != NULL)
981 		return fdt_override;
982 
983 	return fdt_sys;
984 }
985 
986 int
fdt_load_override(char * file)987 fdt_load_override(char *file)
988 {
989 	EFI_DT_FIXUP_PROTOCOL *dt_fixup;
990 	EFI_PHYSICAL_ADDRESS addr;
991 	char path[MAXPATHLEN];
992 	EFI_STATUS status;
993 	struct stat sb;
994 	size_t dt_size;
995 	UINTN sz;
996 	int fd;
997 
998 	if (file == NULL && fdt_override) {
999 		BS->FreePages((uint64_t)fdt_override,
1000 		    EFI_SIZE_TO_PAGES(fdt_override_size));
1001 		fdt_override = NULL;
1002 		fdt_init(fdt_sys);
1003 		return 0;
1004 	}
1005 
1006 	snprintf(path, sizeof(path), "%s:%s", cmd.bootdev, file);
1007 
1008 	fd = open(path, O_RDONLY);
1009 	if (fd < 0 || fstat(fd, &sb) == -1) {
1010 		printf("cannot open %s\n", path);
1011 		return 0;
1012 	}
1013 	dt_size = sb.st_size;
1014 retry:
1015 	if (efi_memprobe_find(EFI_SIZE_TO_PAGES(dt_size),
1016 	    PAGE_SIZE, &addr) != EFI_SUCCESS) {
1017 		printf("cannot allocate memory for %s\n", path);
1018 		return 0;
1019 	}
1020 	if (read(fd, (void *)addr, sb.st_size) != sb.st_size) {
1021 		printf("cannot read from %s\n", path);
1022 		return 0;
1023 	}
1024 
1025 	status = BS->LocateProtocol(&dt_fixup_guid, NULL, (void **)&dt_fixup);
1026 	if (status == EFI_SUCCESS) {
1027 		sz = dt_size;
1028 		status = dt_fixup->Fixup(dt_fixup, (void *)addr, &sz,
1029 		    EFI_DT_APPLY_FIXUPS | EFI_DT_RESERVE_MEMORY);
1030 		if (status == EFI_BUFFER_TOO_SMALL) {
1031 			BS->FreePages(addr, EFI_SIZE_TO_PAGES(dt_size));
1032 			lseek(fd, 0, SEEK_SET);
1033 			dt_size = sz;
1034 			goto retry;
1035 		}
1036 		if (status != EFI_SUCCESS)
1037 			panic("DT fixup failed: 0x%lx", status);
1038 	}
1039 
1040 	if (!fdt_init((void *)addr)) {
1041 		printf("invalid device tree\n");
1042 		BS->FreePages(addr, EFI_SIZE_TO_PAGES(dt_size));
1043 		return 0;
1044 	}
1045 
1046 	if (fdt_override) {
1047 		BS->FreePages((uint64_t)fdt_override,
1048 		    EFI_SIZE_TO_PAGES(fdt_override_size));
1049 		fdt_override = NULL;
1050 	}
1051 
1052 	fdt_override = (void *)addr;
1053 	fdt_override_size = dt_size;
1054 	return 0;
1055 }
1056 
1057 /*
1058  * Commands
1059  */
1060 
1061 int Xdtb_efi(void);
1062 int Xexit_efi(void);
1063 int Xpoweroff_efi(void);
1064 
1065 const struct cmd_table cmd_machine[] = {
1066 	{ "dtb",	CMDT_CMD, Xdtb_efi },
1067 	{ "exit",	CMDT_CMD, Xexit_efi },
1068 	{ "poweroff",	CMDT_CMD, Xpoweroff_efi },
1069 	{ NULL, 0 }
1070 };
1071 
1072 int
Xdtb_efi(void)1073 Xdtb_efi(void)
1074 {
1075 	if (cmd.argc == 1) {
1076 		fdt_load_override(NULL);
1077 		return (0);
1078 	}
1079 
1080 	if (cmd.argc != 2) {
1081 		printf("dtb file\n");
1082 		return (0);
1083 	}
1084 
1085 	return fdt_load_override(cmd.argv[1]);
1086 }
1087 
1088 int
Xexit_efi(void)1089 Xexit_efi(void)
1090 {
1091 	BS->Exit(IH, 0, 0, NULL);
1092 	for (;;)
1093 		continue;
1094 	return (0);
1095 }
1096 
1097 int
Xpoweroff_efi(void)1098 Xpoweroff_efi(void)
1099 {
1100 	RS->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
1101 	return (0);
1102 }
1103