Bug Summary

File:src/sys/arch/amd64/stand/efiboot/bootx64/../efiboot.c
Warning:line 982, column 19
Value stored to 'dp' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name efiboot.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -disable-red-zone -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/stand/efiboot/bootx64/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys/arch/amd64/stand/efiboot/bootx64/../../../../../stand/efi/include/amd64 -D EFIBOOT -D FWRANDOM -D NEEDS_HEAP_H -I /usr/src/sys/arch/amd64/stand/efiboot/bootx64/.. -I /usr/src/sys/arch/amd64/stand/efiboot/bootx64/../../../../../stand/efi/include -I /usr/src/sys/arch/amd64/stand/efiboot/bootx64/../../../../../stand/boot -D SOFTRAID -D _STANDALONE -D MDRANDOM -D BOOT_STTY -I /usr/src/sys/arch/amd64/stand/efiboot/bootx64/../../../../../stand/efi/include/amd64 -D EFIBOOT -D FWRANDOM -D NEEDS_HEAP_H -I /usr/src/sys/arch/amd64/stand/efiboot/bootx64/.. -I /usr/src/sys/arch/amd64/stand/efiboot/bootx64/../../../../../stand/efi/include -I /usr/src/sys/arch/amd64/stand/efiboot/bootx64/../../../../../stand/boot -D SOFTRAID -D _STANDALONE -I /usr/src/sys/arch/amd64/stand/efiboot/bootx64/../../../../.. -I /usr/src/sys/arch/amd64/stand/efiboot/bootx64/../../libsa -I . -I /usr/src/sys/arch/amd64/stand/efiboot/bootx64 -D SMALL -D SLOW -D NOBYFOUR -D __INTERNAL_LIBSA_CREAD -D HEAP_LIMIT=0xc00000 -D HIBERNATE -Oz -Wno-pointer-sign -std=gnu99 -fdebug-compilation-dir=/usr/src/sys/arch/amd64/stand/efiboot/bootx64/obj -ferror-limit 19 -fwrapv -fcf-protection=branch -fno-jump-tables -fno-builtin -fwchar-type=short -fno-signed-wchar -fgnuc-version=4.2.1 -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/sys/arch/amd64/stand/efiboot/bootx64/../efiboot.c
1/* $OpenBSD: efiboot.c,v 1.41 2023/01/02 22:41:17 kettenis Exp $ */
2
3/*
4 * Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/param.h>
20#include <sys/queue.h>
21#include <dev/cons.h>
22#include <dev/isa/isareg.h>
23#include <dev/ic/comreg.h>
24#include <sys/disklabel.h>
25#include <cmd.h>
26#include <stand/boot/bootarg.h>
27#include <machine/pio.h>
28
29#include "libsa.h"
30#include "disk.h"
31
32#include <efi.h>
33#include <efiapi.h>
34#include <efiprot.h>
35#include <eficonsctl.h>
36
37#include "efidev.h"
38#include "efiboot.h"
39#include "run_i386.h"
40
41#define KERN_LOADSPACE_SIZE(64 * 1024 * 1024) (64 * 1024 * 1024)
42
43EFI_SYSTEM_TABLE *ST;
44EFI_BOOT_SERVICES *BS;
45EFI_RUNTIME_SERVICES *RS;
46EFI_HANDLE IH;
47EFI_DEVICE_PATH *efi_bootdp = NULL((void *)0);
48EFI_PHYSICAL_ADDRESS heap;
49EFI_LOADED_IMAGE *loadedImage;
50UINTN heapsiz = 1 * 1024 * 1024;
51UINTN mmap_key;
52static EFI_GUID imgp_guid = LOADED_IMAGE_PROTOCOL{ 0x5B1B31A1, 0x9562, 0x11d2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9,
0x69, 0x72, 0x3B } }
;
53static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL{ 0x964e5b21, 0x6459, 0x11d2, { 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69
, 0x72, 0x3b } }
;
54static EFI_GUID devp_guid = DEVICE_PATH_PROTOCOL{ 0x9576e91, 0x6d3f, 0x11d2, { 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69
, 0x72, 0x3b } }
;
55u_long efi_loadaddr;
56
57int efi_device_path_depth(EFI_DEVICE_PATH *dp, int);
58int efi_device_path_ncmp(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *, int);
59static void efi_heap_init(void);
60static int efi_memprobe_internal(void);
61static void efi_video_init(void);
62static void efi_video_reset(void);
63static EFI_STATUS
64 efi_gop_setmode(int mode);
65EFI_STATUS efi_main(EFI_HANDLE, EFI_SYSTEM_TABLE *);
66
67void (*run_i386)(u_long, u_long, int, int, int, int, int, int, int, int)
68 __attribute__((noreturn));
69
70extern int bios_bootdev;
71
72EFI_STATUS
73efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
74{
75 extern char *progname;
76 EFI_LOADED_IMAGE *imgp;
77 EFI_DEVICE_PATH *dp0 = NULL((void *)0), *dp;
78 EFI_STATUS status;
79 EFI_PHYSICAL_ADDRESS stack;
80
81 ST = systab;
82 BS = ST->BootServices;
83 RS = ST->RuntimeServices;
84 IH = image;
85
86 /* disable reset by watchdog after 5 minutes */
87 BS->SetWatchdogTimer(0, 0, 0, NULL((void *)0));
88
89 efi_video_init();
90 efi_heap_init();
91
92 status = BS->HandleProtocol(image, &imgp_guid, (void **)&imgp);
93 if (status == EFI_SUCCESS0)
94 status = BS->HandleProtocol(imgp->DeviceHandle, &devp_guid,
95 (void **)&dp0);
96 if (status == EFI_SUCCESS0) {
97 for (dp = dp0; !IsDevicePathEnd(dp)( ( ( ((dp)->Type) & 0x7F ) == 0x7f ) && ( (dp
)->SubType == 0xff ) )
;
98 dp = NextDevicePathNode(dp)( (EFI_DEVICE_PATH *) ( ((UINT8 *) (dp)) + ( ((dp)->Length
[0]) | ((dp)->Length[1] << 8) )))
) {
99 if (DevicePathType(dp)( ((dp)->Type) & 0x7F ) == MEDIA_DEVICE_PATH0x04 &&
100 (DevicePathSubType(dp)( (dp)->SubType ) == MEDIA_HARDDRIVE_DP0x01 ||
101 DevicePathSubType(dp)( (dp)->SubType ) == MEDIA_CDROM_DP0x02)) {
102 bios_bootdev =
103 (DevicePathSubType(dp)( (dp)->SubType ) == MEDIA_CDROM_DP0x02)
104 ? 0x1e0 : 0x80;
105 efi_bootdp = dp0;
106 break;
107 } else if (DevicePathType(dp)( ((dp)->Type) & 0x7F ) == MESSAGING_DEVICE_PATH0x03&&
108 DevicePathSubType(dp)( (dp)->SubType ) == MSG_MAC_ADDR_DP0x0b) {
109 bios_bootdev = 0x0;
110 efi_bootdp = dp0;
111 break;
112 }
113 }
114 }
115
116#ifdef __amd64__1
117 /* allocate run_i386_start() on heap */
118 if ((run_i386 = alloc(run_i386_size)) == NULL((void *)0))
119 panic("alloc() failed");
120 memcpy(run_i386, run_i386_start, run_i386_size);
121#endif
122
123 /* can't use sa_cleanup since printf is used after sa_cleanup() */
124 /* sa_cleanup = efi_cleanup; */
125
126#ifdef __amd64__1
127 progname = "BOOTX64";
128#else
129 progname = "BOOTIA32";
130#endif
131
132 /*
133 * Move the stack before calling boot(). UEFI on some machines
134 * locate the stack on our kernel load address.
135 */
136 stack = heap + heapsiz;
137#if defined(__amd64__1)
138 asm("movq %0, %%rsp;"
139 "mov %1, %%edi;"
140 "call boot;"
141 :: "r"(stack - 32), "r"(bios_bootdev));
142#else
143 asm("movl %0, %%esp;"
144 "movl %1, (%%esp);"
145 "call boot;"
146 :: "r"(stack - 32), "r"(bios_bootdev));
147#endif
148 /* must not reach here */
149 return (EFI_SUCCESS0);
150}
151
152void
153efi_cleanup(void)
154{
155 int retry;
156 EFI_STATUS status;
157
158 /* retry once in case of failure */
159 for (retry = 1; retry >= 0; retry--) {
160 efi_memprobe_internal(); /* sync the current map */
161 status = BS->ExitBootServices(IH, mmap_key);
162 if (status == EFI_SUCCESS0)
163 break;
164 if (retry == 0)
165 panic("ExitBootServices failed (%d)", status);
166 }
167}
168
169/***********************************************************************
170 * Disk
171 ***********************************************************************/
172struct disklist_lh efi_disklist;
173
174void
175efi_diskprobe(void)
176{
177 int i, bootdev = 0, depth = -1;
178 UINTN sz;
179 EFI_STATUS status;
180 EFI_HANDLE *handles = NULL((void *)0);
181 EFI_BLOCK_IO *blkio;
182 EFI_BLOCK_IO_MEDIA *media;
183 struct diskinfo *di;
184 EFI_DEVICE_PATH *dp;
185
186 TAILQ_INIT(&efi_disklist)do { (&efi_disklist)->tqh_first = ((void *)0); (&efi_disklist
)->tqh_last = &(&efi_disklist)->tqh_first; } while
(0)
;
187
188 sz = 0;
189 status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, 0);
190 if (status == EFI_BUFFER_TOO_SMALL(0x8000000000000000 | 5)) {
191 handles = alloc(sz);
192 status = BS->LocateHandle(ByProtocol, &blkio_guid,
193 0, &sz, handles);
194 }
195 if (handles == NULL((void *)0) || EFI_ERROR(status)(((INTN) status) < 0))
196 panic("BS->LocateHandle() returns %d", status);
197
198 if (efi_bootdp != NULL((void *)0))
199 depth = efi_device_path_depth(efi_bootdp, MEDIA_DEVICE_PATH0x04);
200
201 /*
202 * U-Boot incorrectly represents devices with a single
203 * MEDIA_DEVICE_PATH component. In that case include that
204 * component into the matching, otherwise we'll blindly select
205 * the first device.
206 */
207 if (depth == 0)
208 depth = 1;
209
210 for (i = 0; i < sz / sizeof(EFI_HANDLE); i++) {
211 status = BS->HandleProtocol(handles[i], &blkio_guid,
212 (void **)&blkio);
213 if (EFI_ERROR(status)(((INTN) status) < 0))
214 panic("BS->HandleProtocol() returns %d", status);
215
216 media = blkio->Media;
217 if (media->LogicalPartition || !media->MediaPresent)
218 continue;
219 di = alloc(sizeof(struct diskinfo));
220 efid_init(di, blkio);
221
222 if (efi_bootdp == NULL((void *)0) || depth == -1 || bootdev != 0)
223 goto next;
224 status = BS->HandleProtocol(handles[i], &devp_guid,
225 (void **)&dp);
226 if (EFI_ERROR(status)(((INTN) status) < 0))
227 goto next;
228 if (efi_device_path_ncmp(efi_bootdp, dp, depth) == 0) {
229 TAILQ_INSERT_HEAD(&efi_disklist, di, list)do { if (((di)->list.tqe_next = (&efi_disklist)->tqh_first
) != ((void *)0)) (&efi_disklist)->tqh_first->list.
tqe_prev = &(di)->list.tqe_next; else (&efi_disklist
)->tqh_last = &(di)->list.tqe_next; (&efi_disklist
)->tqh_first = (di); (di)->list.tqe_prev = &(&efi_disklist
)->tqh_first; } while (0)
;
230 bootdev = 1;
231 continue;
232 }
233next:
234 TAILQ_INSERT_TAIL(&efi_disklist, di, list)do { (di)->list.tqe_next = ((void *)0); (di)->list.tqe_prev
= (&efi_disklist)->tqh_last; *(&efi_disklist)->
tqh_last = (di); (&efi_disklist)->tqh_last = &(di)
->list.tqe_next; } while (0)
;
235 }
236
237 free(handles, sz);
238}
239
240/*
241 * Determine the number of nodes up to, but not including, the first
242 * node of the specified type.
243 */
244int
245efi_device_path_depth(EFI_DEVICE_PATH *dp, int dptype)
246{
247 int i;
248
249 for (i = 0; !IsDevicePathEnd(dp)( ( ( ((dp)->Type) & 0x7F ) == 0x7f ) && ( (dp
)->SubType == 0xff ) )
; dp = NextDevicePathNode(dp)( (EFI_DEVICE_PATH *) ( ((UINT8 *) (dp)) + ( ((dp)->Length
[0]) | ((dp)->Length[1] << 8) )))
, i++) {
250 if (DevicePathType(dp)( ((dp)->Type) & 0x7F ) == dptype)
251 return (i);
252 }
253
254 return (i);
255}
256
257int
258efi_device_path_ncmp(EFI_DEVICE_PATH *dpa, EFI_DEVICE_PATH *dpb, int deptn)
259{
260 int i, cmp;
261
262 for (i = 0; i < deptn; i++) {
263 if (IsDevicePathEnd(dpa)( ( ( ((dpa)->Type) & 0x7F ) == 0x7f ) && ( (dpa
)->SubType == 0xff ) )
|| IsDevicePathEnd(dpb)( ( ( ((dpb)->Type) & 0x7F ) == 0x7f ) && ( (dpb
)->SubType == 0xff ) )
)
264 return ((IsDevicePathEnd(dpa)( ( ( ((dpa)->Type) & 0x7F ) == 0x7f ) && ( (dpa
)->SubType == 0xff ) )
&& IsDevicePathEnd(dpb)( ( ( ((dpb)->Type) & 0x7F ) == 0x7f ) && ( (dpb
)->SubType == 0xff ) )
)
265 ? 0 : (IsDevicePathEnd(dpa)( ( ( ((dpa)->Type) & 0x7F ) == 0x7f ) && ( (dpa
)->SubType == 0xff ) )
)? -1 : 1);
266 cmp = DevicePathNodeLength(dpa)( ((dpa)->Length[0]) | ((dpa)->Length[1] << 8) ) - DevicePathNodeLength(dpb)( ((dpb)->Length[0]) | ((dpb)->Length[1] << 8) );
267 if (cmp)
268 return (cmp);
269 cmp = memcmp(dpa, dpb, DevicePathNodeLength(dpa)( ((dpa)->Length[0]) | ((dpa)->Length[1] << 8) ));
270 if (cmp)
271 return (cmp);
272 dpa = NextDevicePathNode(dpa)( (EFI_DEVICE_PATH *) ( ((UINT8 *) (dpa)) + ( ((dpa)->Length
[0]) | ((dpa)->Length[1] << 8) )))
;
273 dpb = NextDevicePathNode(dpb)( (EFI_DEVICE_PATH *) ( ((UINT8 *) (dpb)) + ( ((dpb)->Length
[0]) | ((dpb)->Length[1] << 8) )))
;
274 }
275
276 return (0);
277}
278
279/***********************************************************************
280 * Memory
281 ***********************************************************************/
282bios_memmap_t bios_memmap[128];
283bios_efiinfo_t bios_efiinfo;
284
285static void
286efi_heap_init(void)
287{
288 EFI_STATUS status;
289
290 heap = HEAP_LIMIT0xc00000;
291 status = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData,
292 EFI_SIZE_TO_PAGES(heapsiz)( ((heapsiz) >> 12) + (((heapsiz) & 0xFFF) ? 1 : 0)
)
, &heap);
293 if (status != EFI_SUCCESS0)
294 panic("BS->AllocatePages()");
295}
296
297void
298efi_memprobe(void)
299{
300 u_int n = 0;
301 bios_memmap_t *bm;
302 EFI_STATUS status;
303 EFI_PHYSICAL_ADDRESS
304 addr = 0x10000000ULL; /* Below 256MB */
305 int error;
306
307 status = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData,
308 EFI_SIZE_TO_PAGES(KERN_LOADSPACE_SIZE)( (((64 * 1024 * 1024)) >> 12) + ((((64 * 1024 * 1024))
& 0xFFF) ? 1 : 0) )
, &addr);
309 if (status != EFI_SUCCESS0)
310 panic("BS->AllocatePages()");
311 efi_loadaddr = addr;
312
313 printf(" mem[");
314 error = efi_memprobe_internal();
315 for (bm = bios_memmap; bm->type != BIOS_MAP_END0x00; bm++) {
316 if (bm->type == BIOS_MAP_FREE0x01 && bm->size > 12 * 1024) {
317 if (n++ != 0)
318 printf(" ");
319 if (bm->size > 1024 * 1024)
320 printf("%uM", bm->size / 1024 / 1024);
321 else
322 printf("%uK", bm->size / 1024);
323 }
324 }
325 if (error == E2BIG7)
326 printf(" overflow");
327 printf("]");
328}
329
330static int
331efi_memprobe_internal(void)
332{
333 EFI_STATUS status;
334 UINTN mapkey, mmsiz, siz;
335 UINT32 mmver;
336 EFI_MEMORY_DESCRIPTOR *mm0, *mm;
337 int i, n;
338 bios_memmap_t *bm, bm0;
339 int error = 0;
340
341 cnvmem = extmem = 0;
342 bios_memmap[0].type = BIOS_MAP_END0x00;
343
344 if (bios_efiinfo.mmap_start != 0)
345 free((void *)bios_efiinfo.mmap_start, bios_efiinfo.mmap_size);
346
347 siz = 0;
348 status = BS->GetMemoryMap(&siz, NULL((void *)0), &mapkey, &mmsiz, &mmver);
349 if (status != EFI_BUFFER_TOO_SMALL(0x8000000000000000 | 5))
350 panic("cannot get the size of memory map");
351 mm0 = alloc(siz);
352 status = BS->GetMemoryMap(&siz, mm0, &mapkey, &mmsiz, &mmver);
353 if (status != EFI_SUCCESS0)
354 panic("cannot get the memory map");
355 n = siz / mmsiz;
356 mmap_key = mapkey;
357
358 for (i = 0, mm = mm0; i < n; i++, mm = NextMemoryDescriptor(mm, mmsiz)((EFI_MEMORY_DESCRIPTOR *) (((UINT8 *) mm) + mmsiz))){
359 bm0.type = BIOS_MAP_END0x00;
360 bm0.addr = mm->PhysicalStart;
361 bm0.size = mm->NumberOfPages * EFI_PAGE_SIZE4096;
362 if (mm->Type == EfiReservedMemoryType ||
363 mm->Type == EfiUnusableMemory ||
364 mm->Type == EfiRuntimeServicesCode ||
365 mm->Type == EfiRuntimeServicesData)
366 bm0.type = BIOS_MAP_RES0x02;
367 else if (mm->Type == EfiLoaderCode ||
368 mm->Type == EfiLoaderData ||
369 mm->Type == EfiBootServicesCode ||
370 mm->Type == EfiBootServicesData ||
371 mm->Type == EfiConventionalMemory)
372 bm0.type = BIOS_MAP_FREE0x01;
373 else if (mm->Type == EfiACPIReclaimMemory)
374 bm0.type = BIOS_MAP_ACPI0x03;
375 else if (mm->Type == EfiACPIMemoryNVS)
376 bm0.type = BIOS_MAP_NVS0x04;
377 else
378 /*
379 * XXX Is there anything to do for EfiMemoryMappedIO
380 * XXX EfiMemoryMappedIOPortSpace EfiPalCode?
381 */
382 bm0.type = BIOS_MAP_RES0x02;
383
384 for (bm = bios_memmap; bm->type != BIOS_MAP_END0x00; bm++) {
385 if (bm->type != bm0.type)
386 continue;
387 if (bm->addr <= bm0.addr &&
388 bm0.addr <= bm->addr + bm->size) {
389 bm->size = bm0.addr + bm0.size - bm->addr;
390 break;
391 } else if (bm0.addr <= bm->addr &&
392 bm->addr <= bm0.addr + bm0.size) {
393 bm->size = bm->addr + bm->size - bm0.addr;
394 bm->addr = bm0.addr;
395 break;
396 }
397 }
398 if (bm->type == BIOS_MAP_END0x00) {
399 if (bm == &bios_memmap[nitems(bios_memmap)(sizeof((bios_memmap)) / sizeof((bios_memmap)[0])) - 1]) {
400 error = E2BIG7;
401 break;
402 }
403 *bm = bm0;
404 (++bm)->type = BIOS_MAP_END0x00;
405 }
406 }
407 for (bm = bios_memmap; bm->type != BIOS_MAP_END0x00; bm++) {
408 if (bm->addr < IOM_BEGIN0x0a0000) /* Below memory hole */
409 cnvmem =
410 max(cnvmem, (bm->addr + bm->size) / 1024)(((cnvmem)>((bm->addr + bm->size) / 1024))? (cnvmem)
: ((bm->addr + bm->size) / 1024))
;
411 if (bm->addr >= IOM_END0x100000 /* Above the memory hole */ &&
412 bm->addr / 1024 == extmem + 1024)
413 extmem += bm->size / 1024;
414 }
415
416 bios_efiinfo.mmap_desc_ver = mmver;
417 bios_efiinfo.mmap_desc_size = mmsiz;
418 bios_efiinfo.mmap_size = siz;
419 bios_efiinfo.mmap_start = (uintptr_t)mm0;
420
421 return error;
422}
423
424/***********************************************************************
425 * Console
426 ***********************************************************************/
427static SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL((void *)0);
428static SIMPLE_INPUT_INTERFACE *conin;
429static EFI_GRAPHICS_OUTPUT *gop = NULL((void *)0);
430static EFI_GUID con_guid
431 = EFI_CONSOLE_CONTROL_PROTOCOL_GUID{ 0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4
, 0xf7, 0x21} }
;
432static EFI_GUID gop_guid
433 = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID{ 0x9042a9de, 0x23dc, 0x4a38, { 0x96, 0xfb, 0x7a, 0xde, 0xd0,
0x80, 0x51, 0x6a } }
;
434static EFI_GUID serio_guid
435 = SERIAL_IO_PROTOCOL{ 0xBB25CF6F, 0xF1D4, 0x11D2, { 0x9A, 0x0C, 0x00, 0x90, 0x27,
0x3F, 0xC1, 0xFD } }
;
436struct efi_video {
437 int cols;
438 int rows;
439} efi_video[32];
440
441static void
442efi_video_init(void)
443{
444 EFI_CONSOLE_CONTROL_PROTOCOL *conctrl = NULL((void *)0);
445 int i, mode80x25, mode100x31;
446 UINTN cols, rows;
447 EFI_STATUS status;
448 EFI_HANDLE *handles;
449 UINTN nhandles;
450 EFI_GRAPHICS_OUTPUT *first_gop = NULL((void *)0);
451 EFI_DEVICE_PATH *devp_test = NULL((void *)0);
452
453 status = BS->LocateHandleBuffer(ByProtocol, &gop_guid, NULL((void *)0), &nhandles,
454 &handles);
455 if (!EFI_ERROR(status)(((INTN) status) < 0)) {
456 for (i = 0; i < nhandles; i++) {
457 status = BS->HandleProtocol(handles[i], &gop_guid,
458 (void **)&gop);
459 if (first_gop == NULL((void *)0))
460 first_gop = gop;
461 status = BS->HandleProtocol(handles[i], &devp_guid,
462 (void **)&devp_test);
463 if (status == EFI_SUCCESS0)
464 break;
465 }
466 if (status != EFI_SUCCESS0)
467 gop = first_gop;
468 BS->FreePool(handles);
469 }
470
471 conout = ST->ConOut;
472 status = BS->LocateProtocol(&con_guid, NULL((void *)0), (void **)&conctrl);
473 if (status == EFI_SUCCESS0)
474 conctrl->SetMode(conctrl, EfiConsoleControlScreenText);
475 mode80x25 = -1;
476 mode100x31 = -1;
477 for (i = 0; i < conout->Mode->MaxMode; i++) {
478 status = conout->QueryMode(conout, i, &cols, &rows);
479 if (EFI_ERROR(status)(((INTN) status) < 0))
480 continue;
481 if (mode80x25 < 0 && cols == 80 && rows == 25)
482 mode80x25 = i;
483 if (mode100x31 < 0 && cols == 100 && rows == 31)
484 mode100x31 = i;
485 if (i < nitems(efi_video)(sizeof((efi_video)) / sizeof((efi_video)[0]))) {
486 efi_video[i].cols = cols;
487 efi_video[i].rows = rows;
488 }
489 }
490 if (mode100x31 >= 0)
491 conout->SetMode(conout, mode100x31);
492 else if (mode80x25 >= 0)
493 conout->SetMode(conout, mode80x25);
494 conin = ST->ConIn;
495 efi_video_reset();
496}
497
498static void
499efi_video_reset(void)
500{
501 conout->EnableCursor(conout, TRUE((BOOLEAN) 1));
502 conout->SetAttribute(conout, EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK)(((0x01 | 0x02 | 0x04)) | ((0x00) << 4)));
503 conout->ClearScreen(conout);
504}
505
506void
507efi_cons_probe(struct consdev *cn)
508{
509 cn->cn_pri = CN_MIDPRI2;
510 cn->cn_dev = makedev(12, 0)((dev_t)((((12) & 0xff) << 8) | ((0) & 0xff) | (
((0) & 0xffff00) << 8)))
;
511 printf(" pc%d", minor(cn->cn_dev)((unsigned)((cn->cn_dev) & 0xff) | (((cn->cn_dev) &
0xffff0000) >> 8))
);
512}
513
514void
515efi_cons_init(struct consdev *cp)
516{
517}
518
519int
520efi_cons_getc(dev_t dev)
521{
522 EFI_INPUT_KEY key;
523 EFI_STATUS status;
524 UINTN dummy;
525 static int lastchar = 0;
526
527 if (lastchar) {
528 int r = lastchar;
529 if ((dev & 0x80) == 0)
530 lastchar = 0;
531 return (r);
532 }
533
534 status = conin->ReadKeyStroke(conin, &key);
535 while (status == EFI_NOT_READY(0x8000000000000000 | 6) || key.UnicodeChar == 0) {
536 if (dev & 0x80)
537 return (0);
538 BS->WaitForEvent(1, &conin->WaitForKey, &dummy);
539 status = conin->ReadKeyStroke(conin, &key);
540 }
541
542 if (dev & 0x80)
543 lastchar = key.UnicodeChar;
544
545 return (key.UnicodeChar);
546}
547
548void
549efi_cons_putc(dev_t dev, int c)
550{
551 CHAR16 buf[2];
552
553 if (c == '\n')
554 efi_cons_putc(dev, '\r');
555
556 buf[0] = c;
557 buf[1] = 0;
558
559 conout->OutputString(conout, buf);
560}
561
562int
563efi_cons_getshifts(dev_t dev)
564{
565 /* XXX */
566 return (0);
567}
568
569int com_addr = -1;
570int com_speed = -1;
571
572static SERIAL_IO_INTERFACE *serios[4];
573const int comports[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
574
575/* call with sp == 0 to query the current speed */
576int
577pio_comspeed(dev_t dev, int sp)
578{
579 int port = (com_addr == -1) ? comports[minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
] : com_addr;
580 int i, newsp;
581 int err;
582
583 if (sp <= 0)
584 return com_speed;
585 /* valid baud rate? */
586 if (115200 < sp || sp < 75)
587 return -1;
588
589 /*
590 * Accepted speeds:
591 * 75 150 300 600 1200 2400 4800 9600 19200 38400 76800 and
592 * 14400 28800 57600 115200
593 */
594 for (i = sp; i != 75 && i != 14400; i >>= 1)
595 if (i & 1)
596 return -1;
597
598/* ripped screaming from dev/ic/com.c */
599#define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
600 newsp = divrnd((COM_FREQ1843200 / 16), sp);
601 if (newsp <= 0)
602 return -1;
603 err = divrnd((COM_FREQ1843200 / 16) * 1000, sp * newsp) - 1000;
604 if (err < 0)
605 err = -err;
606 if (err > COM_TOLERANCE30)
607 return -1;
608#undef divrnd
609
610 if (com_speed != -1 && cn_tab && cn_tab->cn_dev == dev &&
611 com_speed != sp) {
612 printf("com%d: changing speed to %d baud in 5 seconds, "
613 "change your terminal to match!\n\a",
614 minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
, sp);
615 sleep(5);
616 }
617
618 outb(port + com_cfcr, LCR_DLAB)( (__builtin_constant_p((port + 3)) && (port + 3) <
0x100) ? __outbc(port + 3, 0x80) : __outb(port + 3, 0x80))
;
619 outb(port + com_dlbl, newsp)( (__builtin_constant_p((port + 0)) && (port + 0) <
0x100) ? __outbc(port + 0, newsp) : __outb(port + 0, newsp))
;
620 outb(port + com_dlbh, newsp>>8)( (__builtin_constant_p((port + 1)) && (port + 1) <
0x100) ? __outbc(port + 1, newsp>>8) : __outb(port + 1
, newsp>>8))
;
621 outb(port + com_cfcr, LCR_8BITS)( (__builtin_constant_p((port + 3)) && (port + 3) <
0x100) ? __outbc(port + 3, 0x03) : __outb(port + 3, 0x03))
;
622 if (com_speed != -1)
623 printf("\ncom%d: %d baud\n", minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
, sp);
624
625 newsp = com_speed;
626 com_speed = sp;
627 return newsp;
628}
629
630int
631pio_com_getc(dev_t dev)
632{
633 int port = (com_addr == -1) ? comports[minor(dev & 0x7f)((unsigned)((dev & 0x7f) & 0xff) | (((dev & 0x7f)
& 0xffff0000) >> 8))
] : com_addr;
634
635 if (dev & 0x80)
636 return (inb(port + com_lsr)( (__builtin_constant_p((port + 5)) && (port + 5) <
0x100) ? __inbc(port + 5) : __inb(port + 5))
& LSR_RXRDY0x01);
637
638 while ((inb(port + com_lsr)( (__builtin_constant_p((port + 5)) && (port + 5) <
0x100) ? __inbc(port + 5) : __inb(port + 5))
& LSR_RXRDY0x01) == 0)
639 ;
640
641 return (inb(port + com_data)( (__builtin_constant_p((port + 0)) && (port + 0) <
0x100) ? __inbc(port + 0) : __inb(port + 0))
& 0xff);
642}
643
644void
645pio_com_putc(dev_t dev, int c)
646{
647 int port = (com_addr == -1) ? comports[minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
] : com_addr;
648
649 while ((inb(port + com_lsr)( (__builtin_constant_p((port + 5)) && (port + 5) <
0x100) ? __inbc(port + 5) : __inb(port + 5))
& LSR_TXRDY0x20) == 0)
650 ;
651
652 outb(port + com_data, c)( (__builtin_constant_p((port + 0)) && (port + 0) <
0x100) ? __outbc(port + 0, c) : __outb(port + 0, c))
;
653}
654
655void
656efi_com_probe(struct consdev *cn)
657{
658 EFI_HANDLE *handles = NULL((void *)0);
659 SERIAL_IO_INTERFACE *serio;
660 EFI_STATUS status;
661 EFI_DEVICE_PATH *dp, *dp0;
662 EFI_DEV_PATH_PTR dpp;
663 UINTN sz;
664 int i, uid = -1;
665
666 cn->cn_pri = CN_LOWPRI1;
667 cn->cn_dev = makedev(8, 0)((dev_t)((((8) & 0xff) << 8) | ((0) & 0xff) | (
((0) & 0xffff00) << 8)))
;
668
669 sz = 0;
670 status = BS->LocateHandle(ByProtocol, &serio_guid, 0, &sz, 0);
671 if (status == EFI_BUFFER_TOO_SMALL(0x8000000000000000 | 5)) {
672 handles = alloc(sz);
673 status = BS->LocateHandle(ByProtocol, &serio_guid,
674 0, &sz, handles);
675 }
676 if (handles == NULL((void *)0) || EFI_ERROR(status)(((INTN) status) < 0)) {
677 free(handles, sz);
678 return;
679 }
680
681 for (i = 0; i < sz / sizeof(EFI_HANDLE); i++) {
682 /*
683 * Identify port number of the handle. This assumes ACPI
684 * UID 0-3 map to legacy COM[1-4] and they use the legacy
685 * port address.
686 */
687 status = BS->HandleProtocol(handles[i], &devp_guid,
688 (void **)&dp0);
689 if (EFI_ERROR(status)(((INTN) status) < 0))
690 continue;
691 uid = -1;
692 for (dp = dp0; !IsDevicePathEnd(dp)( ( ( ((dp)->Type) & 0x7F ) == 0x7f ) && ( (dp
)->SubType == 0xff ) )
;
693 dp = NextDevicePathNode(dp)( (EFI_DEVICE_PATH *) ( ((UINT8 *) (dp)) + ( ((dp)->Length
[0]) | ((dp)->Length[1] << 8) )))
) {
694 dpp = (EFI_DEV_PATH_PTR)dp;
695 if (DevicePathType(dp)( ((dp)->Type) & 0x7F ) == ACPI_DEVICE_PATH0x02 &&
696 DevicePathSubType(dp)( (dp)->SubType ) == ACPI_DP0x01)
697 if (dpp.Acpi->HID == EFI_PNP_ID(0x0501)(((UINT32) ((0x41d0) | ((0x0501)) << 16)))) {
698 uid = dpp.Acpi->UID;
699 break;
700 }
701 }
702 if (uid < 0 || nitems(serios)(sizeof((serios)) / sizeof((serios)[0])) <= uid)
703 continue;
704
705 /* Prepare SERIAL_IO_INTERFACE */
706 status = BS->HandleProtocol(handles[i], &serio_guid,
707 (void **)&serio);
708 if (EFI_ERROR(status)(((INTN) status) < 0))
709 continue;
710 serios[uid] = serio;
711 }
712 free(handles, sz);
713
714 for (i = 0; i < nitems(serios)(sizeof((serios)) / sizeof((serios)[0])); i++) {
715 if (serios[i] != NULL((void *)0))
716 printf(" com%d", i);
717 }
718}
719
720int
721efi_valid_com(dev_t dev)
722{
723 return (minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
< nitems(serios)(sizeof((serios)) / sizeof((serios)[0])) && serios[minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
] != NULL((void *)0));
724}
725
726int
727comspeed(dev_t dev, int sp)
728{
729 EFI_STATUS status;
730 SERIAL_IO_INTERFACE *serio = serios[minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
];
731 int newsp;
732
733 if (sp <= 0)
734 return com_speed;
735
736 if (!efi_valid_com(dev))
737 return pio_comspeed(dev, sp);
738
739 if (serio->Mode->BaudRate != sp) {
740 status = serio->SetAttributes(serio, sp,
741 serio->Mode->ReceiveFifoDepth,
742 serio->Mode->Timeout, serio->Mode->Parity,
743 serio->Mode->DataBits, serio->Mode->StopBits);
744 if (EFI_ERROR(status)(((INTN) status) < 0)) {
745 printf("com%d: SetAttribute() failed with status=%d\n",
746 minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
, status);
747 return (-1);
748 }
749 if (com_speed != -1)
750 printf("\ncom%d: %d baud\n", minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
, sp);
751 }
752
753 /* same as comspeed() in libsa/bioscons.c */
754 newsp = com_speed;
755 com_speed = sp;
756
757 return (newsp);
758}
759
760void
761efi_com_init(struct consdev *cn)
762{
763 if (!efi_valid_com(cn->cn_dev))
764 /* This actually happens if the machine has another serial. */
765 return;
766
767 if (com_speed == -1)
768 comspeed(cn->cn_dev, 9600); /* default speed is 9600 baud */
769}
770
771int
772efi_com_getc(dev_t dev)
773{
774 EFI_STATUS status;
775 SERIAL_IO_INTERFACE *serio;
776 UINTN sz;
777 u_char buf;
778 static u_char lastchar = 0;
779
780 if (!efi_valid_com(dev & 0x7f))
781 return pio_com_getc(dev);
782 serio = serios[minor(dev & 0x7f)((unsigned)((dev & 0x7f) & 0xff) | (((dev & 0x7f)
& 0xffff0000) >> 8))
];
783
784 if (lastchar != 0) {
785 int r = lastchar;
786 if ((dev & 0x80) == 0)
787 lastchar = 0;
788 return (r);
789 }
790
791 for (;;) {
792 sz = 1;
793 status = serio->Read(serio, &sz, &buf);
794 if (status == EFI_SUCCESS0 && sz > 0)
795 break;
796 if (status != EFI_TIMEOUT(0x8000000000000000 | 18) && EFI_ERROR(status)(((INTN) status) < 0))
797 panic("Error reading from serial status=%d", status);
798 if (dev & 0x80)
799 return (0);
800 }
801
802 if (dev & 0x80)
803 lastchar = buf;
804
805 return (buf);
806}
807
808void
809efi_com_putc(dev_t dev, int c)
810{
811 SERIAL_IO_INTERFACE *serio;
812 UINTN sz = 1;
813 u_char buf;
814
815 if (!efi_valid_com(dev)) {
816 pio_com_putc(dev, c);
817 return;
818 }
819 serio = serios[minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
];
820 buf = c;
821 serio->Write(serio, &sz, &buf);
822}
823
824/***********************************************************************
825 * Miscellaneous
826 ***********************************************************************/
827/*
828 * ACPI GUID is confusing in UEFI spec.
829 * {EFI_,}_ACPI_20_TABLE_GUID or EFI_ACPI_TABLE_GUID means
830 * ACPI 2.0 or above.
831 */
832static EFI_GUID acpi_guid = ACPI_20_TABLE_GUID{ 0x8868e871, 0xe4f1, 0x11d3, { 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c
, 0x88, 0x81 } }
;
833static EFI_GUID smbios_guid = SMBIOS_TABLE_GUID{ 0xeb9d2d31, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f
, 0xc1, 0x4d } }
;
834static EFI_GUID esrt_guid = EFI_SYSTEM_RESOURCE_TABLE_GUID{ 0xb122a263, 0x3661, 0x4f68, { 0x99, 0x29, 0x78, 0xf8, 0xb0,
0xd6, 0x21, 0x80 } }
;
835static int gopmode = -1;
836
837#define efi_guidcmp(_a, _b)memcmp((_a), (_b), sizeof(EFI_GUID)) memcmp((_a), (_b), sizeof(EFI_GUID))
838
839static EFI_STATUS
840efi_gop_setmode(int mode)
841{
842 EFI_STATUS status;
843
844 status = gop->SetMode(gop, mode);
845 if (EFI_ERROR(status)(((INTN) status) < 0) || gop->Mode->Mode != mode)
846 printf("GOP SetMode() failed (%d)\n", status);
847
848 return (status);
849}
850
851void
852efi_makebootargs(void)
853{
854 int i;
855 EFI_STATUS status;
856 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
857 *gopi;
858 bios_efiinfo_t *ei = &bios_efiinfo;
859 int curmode;
860 UINTN sz, gopsiz, bestsiz = 0;
861
862 /*
863 * ACPI, BIOS configuration table
864 */
865 for (i = 0; i < ST->NumberOfTableEntries; i++) {
866 if (efi_guidcmp(&acpi_guid,memcmp((&acpi_guid), (&ST->ConfigurationTable[i].VendorGuid
), sizeof(EFI_GUID))
867 &ST->ConfigurationTable[i].VendorGuid)memcmp((&acpi_guid), (&ST->ConfigurationTable[i].VendorGuid
), sizeof(EFI_GUID))
== 0)
868 ei->config_acpi = (uintptr_t)
869 ST->ConfigurationTable[i].VendorTable;
870 else if (efi_guidcmp(&smbios_guid,memcmp((&smbios_guid), (&ST->ConfigurationTable[i]
.VendorGuid), sizeof(EFI_GUID))
871 &ST->ConfigurationTable[i].VendorGuid)memcmp((&smbios_guid), (&ST->ConfigurationTable[i]
.VendorGuid), sizeof(EFI_GUID))
== 0)
872 ei->config_smbios = (uintptr_t)
873 ST->ConfigurationTable[i].VendorTable;
874 else if (efi_guidcmp(&esrt_guid,memcmp((&esrt_guid), (&ST->ConfigurationTable[i].VendorGuid
), sizeof(EFI_GUID))
875 &ST->ConfigurationTable[i].VendorGuid)memcmp((&esrt_guid), (&ST->ConfigurationTable[i].VendorGuid
), sizeof(EFI_GUID))
== 0)
876 ei->config_esrt = (uintptr_t)
877 ST->ConfigurationTable[i].VendorTable;
878 }
879
880 /*
881 * Need to copy ESRT because call to ExitBootServices() frees memory of
882 * type EfiBootServicesData in which ESRT resides.
883 */
884 if (ei->config_esrt != 0) {
885 EFI_SYSTEM_RESOURCE_TABLE *esrt =
886 (EFI_SYSTEM_RESOURCE_TABLE *)ei->config_esrt;
887 size_t esrt_size = sizeof(*esrt) +
888 esrt->FwResourceCount * sizeof(EFI_SYSTEM_RESOURCE_ENTRY);
889 void *esrt_copy;
890
891 /*
892 * Using EfiRuntimeServicesData as it maps to BIOS_MAP_RES,
893 * while EfiLoaderData becomes BIOS_MAP_FREE.
894 */
895 status = BS->AllocatePool(EfiRuntimeServicesData,
896 esrt_size, &esrt_copy);
897 if (status == EFI_SUCCESS0) {
898 memcpy(esrt_copy, esrt, esrt_size);
899 ei->config_esrt = (uintptr_t)esrt_copy;
900 ei->flags |= BEI_ESRT0x00000002;
901 }
902 }
903
904 /*
905 * Frame buffer
906 */
907 if (gop != NULL((void *)0)) {
908 if (gopmode < 0) {
909 for (i = 0; i < gop->Mode->MaxMode; i++) {
910 status = gop->QueryMode(gop, i, &sz, &gopi);
911 if (EFI_ERROR(status)(((INTN) status) < 0))
912 continue;
913 gopsiz = gopi->HorizontalResolution *
914 gopi->VerticalResolution;
915 if (gopsiz > bestsiz) {
916 gopmode = i;
917 bestsiz = gopsiz;
918 }
919 }
920 }
921 if (gopmode >= 0 && gopmode != gop->Mode->Mode) {
922 curmode = gop->Mode->Mode;
923 if (efi_gop_setmode(gopmode) != EFI_SUCCESS0)
924 (void)efi_gop_setmode(curmode);
925 }
926
927 gopi = gop->Mode->Info;
928 switch (gopi->PixelFormat) {
929 case PixelBlueGreenRedReserved8BitPerColor:
930 ei->fb_red_mask = 0x00ff0000;
931 ei->fb_green_mask = 0x0000ff00;
932 ei->fb_blue_mask = 0x000000ff;
933 ei->fb_reserved_mask = 0xff000000;
934 break;
935 case PixelRedGreenBlueReserved8BitPerColor:
936 ei->fb_red_mask = 0x000000ff;
937 ei->fb_green_mask = 0x0000ff00;
938 ei->fb_blue_mask = 0x00ff0000;
939 ei->fb_reserved_mask = 0xff000000;
940 break;
941 case PixelBitMask:
942 ei->fb_red_mask = gopi->PixelInformation.RedMask;
943 ei->fb_green_mask = gopi->PixelInformation.GreenMask;
944 ei->fb_blue_mask = gopi->PixelInformation.BlueMask;
945 ei->fb_reserved_mask =
946 gopi->PixelInformation.ReservedMask;
947 break;
948 default:
949 break;
950 }
951 ei->fb_addr = gop->Mode->FrameBufferBase;
952 ei->fb_size = gop->Mode->FrameBufferSize;
953 ei->fb_height = gopi->VerticalResolution;
954 ei->fb_width = gopi->HorizontalResolution;
955 ei->fb_pixpsl = gopi->PixelsPerScanLine;
956 }
957
958 /*
959 * EFI system table
960 */
961 ei->system_table = (uintptr_t)ST;
962
963#ifdef __amd64__1
964 ei->flags |= BEI_64BIT0x00000001;
965#endif
966
967 addbootarg(BOOTARG_EFIINFO11, sizeof(bios_efiinfo), &bios_efiinfo);
968}
969
970/* Vendor device path used to indicate the mmio UART on AMD SoCs. */
971#define AMDSOC_DEVPATH{ 0xe76fd4e9, 0x0a30, 0x4ca9, { 0x95, 0x40, 0xd7, 0x99, 0x53,
0x4c, 0xc4, 0xff } }
\
972 { 0xe76fd4e9, 0x0a30, 0x4ca9, \
973 { 0x95, 0x40, 0xd7, 0x99, 0x53, 0x4c, 0xc4, 0xff } }
974
975void
976efi_setconsdev(void)
977{
978 bios_consdev_t cd;
979 EFI_STATUS status;
980 UINT8 data[128];
981 UINTN size = sizeof(data);
982 EFI_DEVICE_PATH *dp = (void *)data;
Value stored to 'dp' during its initialization is never read
983 VENDOR_DEVICE_PATH *vdp;
984 UART_DEVICE_PATH *udp;
985 EFI_GUID global = EFI_GLOBAL_VARIABLE{ 0x8BE4DF61, 0x93CA, 0x11d2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98,
0x03, 0x2B, 0x8C } }
;
986 EFI_GUID amdsoc = AMDSOC_DEVPATH{ 0xe76fd4e9, 0x0a30, 0x4ca9, { 0x95, 0x40, 0xd7, 0x99, 0x53,
0x4c, 0xc4, 0xff } }
;
987
988 memset(&cd, 0, sizeof(cd));
989 cd.consdev = cn_tab->cn_dev;
990 cd.conspeed = com_speed;
991 cd.consaddr = com_addr;
992
993 /*
994 * If the ConOut variable indicates we're using a serial
995 * console, use it to determine the baud rate.
996 */
997 status = RS->GetVariable(L"ConOut", &global, NULL((void *)0), &size, &data);
998 if (status == EFI_SUCCESS0) {
999 for (dp = (void *)data; !IsDevicePathEnd(dp)( ( ( ((dp)->Type) & 0x7F ) == 0x7f ) && ( (dp
)->SubType == 0xff ) )
;
1000 dp = NextDevicePathNode(dp)( (EFI_DEVICE_PATH *) ( ((UINT8 *) (dp)) + ( ((dp)->Length
[0]) | ((dp)->Length[1] << 8) )))
) {
1001 /*
1002 * AMD Ryzen Embedded V1000 SoCs integrate a
1003 * Synopsys DesignWare UART that is not
1004 * compatible with the traditional 8250 UART
1005 * found on the IBM PC. Pass the magic
1006 * parameters to the kernel to make this UART
1007 * work.
1008 */
1009 if (DevicePathType(dp)( ((dp)->Type) & 0x7F ) == HARDWARE_DEVICE_PATH0x01 &&
1010 DevicePathSubType(dp)( (dp)->SubType ) == HW_VENDOR_DP0x04) {
1011 vdp = (VENDOR_DEVICE_PATH *)dp;
1012 if (efi_guidcmp(&vdp->Guid, &amdsoc)memcmp((&vdp->Guid), (&amdsoc), sizeof(EFI_GUID)) == 0) {
1013 cd.consdev = makedev(8, 4)((dev_t)((((8) & 0xff) << 8) | ((4) & 0xff) | (
((4) & 0xffff00) << 8)))
;
1014 cd.consaddr = *(uint64_t *)(vdp + 1);
1015 cd.consfreq = 48000000;
1016 cd.flags = BCD_MMIO0x00000001;
1017 cd.reg_width = 4;
1018 cd.reg_shift = 2;
1019 }
1020 }
1021
1022 if (DevicePathType(dp)( ((dp)->Type) & 0x7F ) == MESSAGING_DEVICE_PATH0x03 &&
1023 DevicePathSubType(dp)( (dp)->SubType ) == MSG_UART_DP0x0e) {
1024 udp = (UART_DEVICE_PATH *)dp;
1025 if (cd.conspeed == -1)
1026 cd.conspeed = udp->BaudRate;
1027 }
1028 }
1029 }
1030
1031 addbootarg(BOOTARG_CONSDEV5, sizeof(cd), &cd);
1032}
1033
1034void
1035_rtt(void)
1036{
1037#ifdef EFI_DEBUG
1038 printf("Hit any key to reboot\n");
1039 efi_cons_getc(0);
1040#endif
1041 RS->ResetSystem(EfiResetCold, EFI_SUCCESS0, 0, NULL((void *)0));
1042 for (;;)
1043 continue;
1044}
1045
1046time_t
1047getsecs(void)
1048{
1049 EFI_TIME t;
1050 time_t r = 0;
1051 int y = 0;
1052 const int daytab[][14] = {
1053 { 0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 },
1054 { 0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
1055 };
1056#define isleap(_y)(((_y) % 4) == 0 && (((_y) % 100) != 0 || ((_y) % 400
) == 0))
(((_y) % 4) == 0 && (((_y) % 100) != 0 || ((_y) % 400) == 0))
1057
1058 ST->RuntimeServices->GetTime(&t, NULL((void *)0));
1059
1060 /* Calc days from UNIX epoch */
1061 r = (t.Year - 1970) * 365;
1062 for (y = 1970; y < t.Year; y++) {
1063 if (isleap(y)(((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) ==
0))
)
1064 r++;
1065 }
1066 r += daytab[isleap(t.Year)(((t.Year) % 4) == 0 && (((t.Year) % 100) != 0 || ((t
.Year) % 400) == 0))
? 1 : 0][t.Month] + t.Day;
1067
1068 /* Calc secs */
1069 r *= 60 * 60 * 24;
1070 r += ((t.Hour * 60) + t.Minute) * 60 + t.Second;
1071 if (-24 * 60 < t.TimeZone && t.TimeZone < 24 * 60)
1072 r += t.TimeZone * 60;
1073
1074 return (r);
1075}
1076
1077u_int
1078sleep(u_int i)
1079{
1080 time_t t;
1081
1082 /*
1083 * Loop for the requested number of seconds, polling,
1084 * so that it may handle interrupts.
1085 */
1086 for (t = getsecs() + i; getsecs() < t; cnischar())
1087 ;
1088
1089 return 0;
1090}
1091
1092/***********************************************************************
1093 * Commands
1094 ***********************************************************************/
1095int
1096Xexit_efi(void)
1097{
1098 BS->Exit(IH, 0, 0, NULL((void *)0));
1099 for (;;)
1100 continue;
1101 return (0);
1102}
1103
1104int
1105Xvideo_efi(void)
1106{
1107 int i, mode = -1;
1108
1109 if (cmd.argc >= 2) {
1110 mode = strtol(cmd.argv[1], NULL((void *)0), 10);
1111 if (0 <= mode && mode < nitems(efi_video)(sizeof((efi_video)) / sizeof((efi_video)[0])) &&
1112 efi_video[mode].cols > 0) {
1113 conout->SetMode(conout, mode);
1114 efi_video_reset();
1115 }
1116 } else {
1117 for (i = 0; i < nitems(efi_video)(sizeof((efi_video)) / sizeof((efi_video)[0])) &&
1118 i < conout->Mode->MaxMode; i++) {
1119 if (efi_video[i].cols > 0)
1120 printf("Mode %d: %d x %d\n", i,
1121 efi_video[i].cols,
1122 efi_video[i].rows);
1123 }
1124 printf("\n");
1125 }
1126 printf("Current Mode = %d\n", conout->Mode->Mode);
1127
1128 return (0);
1129}
1130
1131int
1132Xpoweroff_efi(void)
1133{
1134 RS->ResetSystem(EfiResetShutdown, EFI_SUCCESS0, 0, NULL((void *)0));
1135 return (0);
1136}
1137
1138int
1139Xgop_efi(void)
1140{
1141 EFI_STATUS status;
1142 int i, mode = -1;
1143 UINTN sz;
1144 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
1145 *gopi;
1146
1147 if (gop == NULL((void *)0)) {
1148 printf("No GOP found\n");
1149 return (0);
1150 }
1151 if (cmd.argc >= 2) {
1152 mode = strtol(cmd.argv[1], NULL((void *)0), 10);
1153 if (0 <= mode && mode < gop->Mode->MaxMode) {
1154 status = gop->QueryMode(gop, mode, &sz, &gopi);
1155 if (!EFI_ERROR(status)(((INTN) status) < 0)) {
1156 if (efi_gop_setmode(mode) == EFI_SUCCESS0)
1157 gopmode = mode;
1158 }
1159 }
1160 } else {
1161 for (i = 0; i < gop->Mode->MaxMode; i++) {
1162 status = gop->QueryMode(gop, i, &sz, &gopi);
1163 if (EFI_ERROR(status)(((INTN) status) < 0))
1164 continue;
1165 printf("Mode %d: %d x %d (stride = %d)\n", i,
1166 gopi->HorizontalResolution,
1167 gopi->VerticalResolution,
1168 gopi->PixelsPerScanLine);
1169 }
1170 printf("\n");
1171 }
1172 printf("Current Mode = %d\n", gop->Mode->Mode);
1173
1174 return (0);
1175}