]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - sys/boot/ia64/efi/main.c
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.git] / sys / boot / ia64 / efi / main.c
1 /*-
2  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3  * Copyright (c) 1998,2000 Doug Rabson <dfr@freebsd.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <stand.h>
32 #include <string.h>
33 #include <setjmp.h>
34 #include <machine/sal.h>
35 #include <machine/pal.h>
36 #include <machine/pte.h>
37 #include <machine/dig64.h>
38
39 #include <efi.h>
40 #include <efilib.h>
41
42 #include <libia64.h>
43
44 /* DIG64 Headless Console & Debug Port Table. */
45 #define HCDP_TABLE_GUID         \
46     {0xf951938d,0x620b,0x42ef,{0x82,0x79,0xa8,0x4b,0x79,0x61,0x78,0x98}}
47  
48 extern char bootprog_name[];
49 extern char bootprog_rev[];
50 extern char bootprog_date[];
51 extern char bootprog_maker[];
52
53 struct arch_switch archsw;      /* MI/MD interface boundary */
54
55 extern u_int64_t        ia64_pal_entry;
56
57 EFI_GUID acpi = ACPI_TABLE_GUID;
58 EFI_GUID acpi20 = ACPI_20_TABLE_GUID;
59 EFI_GUID devid = DEVICE_PATH_PROTOCOL;
60 EFI_GUID hcdp = HCDP_TABLE_GUID;
61 EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
62 EFI_GUID mps = MPS_TABLE_GUID;
63 EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL;
64 EFI_GUID sal = SAL_SYSTEM_TABLE_GUID;
65 EFI_GUID smbios = SMBIOS_TABLE_GUID;
66
67 static void
68 find_pal_proc(void)
69 {
70         int i;
71         struct sal_system_table *saltab = 0;
72         static int sizes[6] = {
73                 48, 32, 16, 32, 16, 16
74         };
75         u_int8_t *p;
76
77         saltab = efi_get_table(&sal);
78         if (saltab == NULL) {
79                 printf("Can't find SAL System Table\n");
80                 return;
81         }
82
83         if (memcmp(saltab->sal_signature, "SST_", 4)) {
84                 printf("Bad signature for SAL System Table\n");
85                 return;
86         }
87
88         p = (u_int8_t *) (saltab + 1);
89         for (i = 0; i < saltab->sal_entry_count; i++) {
90                 if (*p == 0) {
91                         struct sal_entrypoint_descriptor *dp;
92                         dp = (struct sal_entrypoint_descriptor *) p;
93                         ia64_pal_entry = dp->sale_pal_proc;
94                         return;
95                 }
96                 p += sizes[*p];
97         }
98
99         printf("Can't find PAL proc\n");
100         return;
101 }
102
103 static int
104 usc2cmp(CHAR16 *s1, CHAR16 *s2)
105 {
106
107         while (*s1 == *s2++) {
108                 if (*s1++ == 0)
109                         return (0);
110         }
111         return (*s1 - *(s2 - 1));
112 }
113
114 static char *
115 get_dev_option(int argc, CHAR16 *argv[])
116 {
117         static char dev[32];
118         CHAR16 *arg;
119         char *devp;
120         int i, j;
121
122         devp = NULL;
123         for (i = 0; i < argc; i++) {
124                 if (usc2cmp(argv[i], L"-dev") == 0 && i < argc - 1) {
125                         arg = argv[i + 1];
126                         j = 0;
127                         while (j < sizeof(dev) && *arg != 0)
128                                 dev[j++] = *arg++;
129                         if (j == sizeof(dev))
130                                 j--;
131                         dev[j] = '\0';
132                         devp = dev;
133                         break;
134                 }
135         }
136
137         return (devp);
138 }
139
140 EFI_STATUS
141 main(int argc, CHAR16 *argv[])
142 {
143         struct devdesc currdev;
144         EFI_LOADED_IMAGE *img;
145         char *dev;
146         int i;
147
148         /* 
149          * XXX Chicken-and-egg problem; we want to have console output
150          * early, but some console attributes may depend on reading from
151          * eg. the boot device, which we can't do yet.  We can use
152          * printf() etc. once this is done.
153          */
154         cons_probe();
155
156         printf("\n%s, Revision %s\n", bootprog_name, bootprog_rev);
157
158         find_pal_proc();
159
160         /*
161          * March through the device switch probing for things.
162          */
163         for (i = 0; devsw[i] != NULL; i++)
164                 if (devsw[i]->dv_init != NULL)
165                         (devsw[i]->dv_init)();
166
167         /*
168          * Disable the watchdog timer. By default the boot manager sets
169          * the timer to 5 minutes before invoking a boot option. If we
170          * want to return to the boot manager, we have to disable the
171          * watchdog timer and since we're an interactive program, we don't
172          * want to wait until the user types "quit". The timer may have
173          * fired by then. We don't care if this fails. It does not prevent
174          * normal functioning in any way...
175          */
176         BS->SetWatchdogTimer(0, 0, 0, NULL);
177
178         /* Get our loaded image protocol interface structure. */
179         BS->HandleProtocol(IH, &imgid, (VOID**)&img);
180
181         bzero(&currdev, sizeof(currdev));
182         efi_handle_lookup(img->DeviceHandle, &currdev.d_dev,
183             &currdev.d_unit, NULL);
184         currdev.d_type = currdev.d_dev->dv_type;
185
186         env_setenv("loaddev", EV_VOLATILE, ia64_fmtdev(&currdev), env_noset,
187             env_nounset);
188
189         dev = get_dev_option(argc, argv);
190         if (dev == NULL)
191                 dev = ia64_fmtdev(&currdev);
192
193         env_setenv("currdev", EV_VOLATILE, dev, ia64_setcurrdev, env_nounset);
194
195         setenv("LINES", "24", 1);       /* optional */
196
197         archsw.arch_autoload = ia64_autoload;
198         archsw.arch_copyin = ia64_copyin;
199         archsw.arch_copyout = ia64_copyout;
200         archsw.arch_getdev = ia64_getdev;
201         archsw.arch_loadaddr = ia64_loadaddr;
202         archsw.arch_loadseg = ia64_loadseg;
203         archsw.arch_readin = ia64_readin;
204
205         interact();                     /* doesn't return */
206
207         return (EFI_SUCCESS);           /* keep compiler happy */
208 }
209
210 COMMAND_SET(quit, "quit", "exit the loader", command_quit);
211
212 static int
213 command_quit(int argc, char *argv[])
214 {
215         exit(0);
216         /* NOTREACHED */
217         return (CMD_OK);
218 }
219
220 COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
221  
222 static int
223 command_reboot(int argc, char *argv[])
224 {
225
226         RS->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
227         /* NOTREACHED */
228         return (CMD_OK);
229 }
230
231 COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
232
233 static int
234 command_memmap(int argc, char *argv[])
235 {
236         UINTN sz;
237         EFI_MEMORY_DESCRIPTOR *map, *p;
238         UINTN key, dsz;
239         UINT32 dver;
240         EFI_STATUS status;
241         int i, ndesc;
242         static char *types[] = {
243             "Reserved",
244             "LoaderCode",
245             "LoaderData",
246             "BootServicesCode",
247             "BootServicesData",
248             "RuntimeServicesCode",
249             "RuntimeServicesData",
250             "ConventionalMemory",
251             "UnusableMemory",
252             "ACPIReclaimMemory",
253             "ACPIMemoryNVS",
254             "MemoryMappedIO",
255             "MemoryMappedIOPortSpace",
256             "PalCode"
257         };
258
259         sz = 0;
260         status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
261         if (status != EFI_BUFFER_TOO_SMALL) {
262                 printf("Can't determine memory map size\n");
263                 return CMD_ERROR;
264         }
265         map = malloc(sz);
266         status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
267         if (EFI_ERROR(status)) {
268                 printf("Can't read memory map\n");
269                 return CMD_ERROR;
270         }
271
272         ndesc = sz / dsz;
273         printf("%23s %12s %12s %8s %4s\n",
274                "Type", "Physical", "Virtual", "#Pages", "Attr");
275                
276         for (i = 0, p = map; i < ndesc;
277              i++, p = NextMemoryDescriptor(p, dsz)) {
278             printf("%23s %012lx %012lx %08lx ",
279                    types[p->Type],
280                    p->PhysicalStart,
281                    p->VirtualStart,
282                    p->NumberOfPages);
283             if (p->Attribute & EFI_MEMORY_UC)
284                 printf("UC ");
285             if (p->Attribute & EFI_MEMORY_WC)
286                 printf("WC ");
287             if (p->Attribute & EFI_MEMORY_WT)
288                 printf("WT ");
289             if (p->Attribute & EFI_MEMORY_WB)
290                 printf("WB ");
291             if (p->Attribute & EFI_MEMORY_UCE)
292                 printf("UCE ");
293             if (p->Attribute & EFI_MEMORY_WP)
294                 printf("WP ");
295             if (p->Attribute & EFI_MEMORY_RP)
296                 printf("RP ");
297             if (p->Attribute & EFI_MEMORY_XP)
298                 printf("XP ");
299             if (p->Attribute & EFI_MEMORY_RUNTIME)
300                 printf("RUNTIME");
301             printf("\n");
302         }
303
304         return CMD_OK;
305 }
306
307 COMMAND_SET(configuration, "configuration",
308             "print configuration tables", command_configuration);
309
310 static const char *
311 guid_to_string(EFI_GUID *guid)
312 {
313         static char buf[40];
314
315         sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
316             guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
317             guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
318             guid->Data4[5], guid->Data4[6], guid->Data4[7]);
319         return (buf);
320 }
321
322 static int
323 command_configuration(int argc, char *argv[])
324 {
325         int i;
326
327         printf("NumberOfTableEntries=%ld\n", ST->NumberOfTableEntries);
328         for (i = 0; i < ST->NumberOfTableEntries; i++) {
329                 EFI_GUID *guid;
330
331                 printf("  ");
332                 guid = &ST->ConfigurationTable[i].VendorGuid;
333                 if (!memcmp(guid, &mps, sizeof(EFI_GUID)))
334                         printf("MPS Table");
335                 else if (!memcmp(guid, &acpi, sizeof(EFI_GUID)))
336                         printf("ACPI Table");
337                 else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID)))
338                         printf("ACPI 2.0 Table");
339                 else if (!memcmp(guid, &smbios, sizeof(EFI_GUID)))
340                         printf("SMBIOS Table");
341                 else if (!memcmp(guid, &sal, sizeof(EFI_GUID)))
342                         printf("SAL System Table");
343                 else if (!memcmp(guid, &hcdp, sizeof(EFI_GUID)))
344                         printf("DIG64 HCDP Table");
345                 else
346                         printf("Unknown Table (%s)", guid_to_string(guid));
347                 printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
348         }
349
350         return CMD_OK;
351 }    
352
353 COMMAND_SET(sal, "sal", "print SAL System Table", command_sal);
354
355 static int
356 command_sal(int argc, char *argv[])
357 {
358         int i;
359         struct sal_system_table *saltab = 0;
360         static int sizes[6] = {
361                 48, 32, 16, 32, 16, 16
362         };
363         u_int8_t *p;
364
365         saltab = efi_get_table(&sal);
366         if (saltab == NULL) {
367                 printf("Can't find SAL System Table\n");
368                 return CMD_ERROR;
369         }
370
371         if (memcmp(saltab->sal_signature, "SST_", 4)) {
372                 printf("Bad signature for SAL System Table\n");
373                 return CMD_ERROR;
374         }
375
376         printf("SAL Revision %x.%02x\n",
377                saltab->sal_rev[1],
378                saltab->sal_rev[0]);
379         printf("SAL A Version %x.%02x\n",
380                saltab->sal_a_version[1],
381                saltab->sal_a_version[0]);
382         printf("SAL B Version %x.%02x\n",
383                saltab->sal_b_version[1],
384                saltab->sal_b_version[0]);
385
386         p = (u_int8_t *) (saltab + 1);
387         for (i = 0; i < saltab->sal_entry_count; i++) {
388                 printf("  Desc %d", *p);
389                 if (*p == 0) {
390                         struct sal_entrypoint_descriptor *dp;
391                         dp = (struct sal_entrypoint_descriptor *) p;
392                         printf("\n");
393                         printf("    PAL Proc at 0x%lx\n",
394                                dp->sale_pal_proc);
395                         printf("    SAL Proc at 0x%lx\n",
396                                dp->sale_sal_proc);
397                         printf("    SAL GP at 0x%lx\n",
398                                dp->sale_sal_gp);
399                 } else if (*p == 1) {
400                         struct sal_memory_descriptor *dp;
401                         dp = (struct sal_memory_descriptor *) p;
402                         printf(" Type %d.%d, ",
403                                dp->sale_memory_type[0],
404                                dp->sale_memory_type[1]);
405                         printf("Address 0x%lx, ",
406                                dp->sale_physical_address);
407                         printf("Length 0x%x\n",
408                                dp->sale_length);
409                 } else if (*p == 5) {
410                         struct sal_ap_wakeup_descriptor *dp;
411                         dp = (struct sal_ap_wakeup_descriptor *) p;
412                         printf("\n");
413                         printf("    Mechanism %d\n", dp->sale_mechanism);
414                         printf("    Vector 0x%lx\n", dp->sale_vector);
415                 } else
416                         printf("\n");
417
418                 p += sizes[*p];
419         }
420
421         return CMD_OK;
422 }
423
424 int
425 print_trs(int type)
426 {
427         struct ia64_pal_result res;
428         int i, maxtr;
429         struct {
430                 pt_entry_t      pte;
431                 uint64_t        itir;
432                 uint64_t        ifa;
433                 struct ia64_rr  rr;
434         } buf;
435         static const char *psnames[] = {
436                 "1B",   "2B",   "4B",   "8B",
437                 "16B",  "32B",  "64B",  "128B",
438                 "256B", "512B", "1K",   "2K",
439                 "4K",   "8K",   "16K",  "32K",
440                 "64K",  "128K", "256K", "512K",
441                 "1M",   "2M",   "4M",   "8M",
442                 "16M",  "32M",  "64M",  "128M",
443                 "256M", "512M", "1G",   "2G"
444         };
445         static const char *manames[] = {
446                 "WB",   "bad",  "bad",  "bad",
447                 "UC",   "UCE",  "WC",   "NaT",
448         };
449
450         res = ia64_call_pal_static(PAL_VM_SUMMARY, 0, 0, 0);
451         if (res.pal_status != 0) {
452                 printf("Can't get VM summary\n");
453                 return CMD_ERROR;
454         }
455
456         if (type == 0)
457                 maxtr = (res.pal_result[0] >> 40) & 0xff;
458         else
459                 maxtr = (res.pal_result[0] >> 32) & 0xff;
460
461         printf("%d translation registers\n", maxtr);
462
463         pager_open();
464         pager_output("TR# RID    Virtual Page  Physical Page PgSz ED AR PL D A MA  P KEY\n");
465         for (i = 0; i <= maxtr; i++) {
466                 char lbuf[128];
467
468                 bzero(&buf, sizeof(buf));
469                 res = ia64_call_pal_stacked(PAL_VM_TR_READ, i, type,
470                                             (u_int64_t) &buf);
471                 if (res.pal_status != 0)
472                         break;
473
474                 /* Only display valid translations */
475                 if ((buf.ifa & 1) == 0)
476                         continue;
477
478                 if (!(res.pal_result[0] & 1))
479                         buf.pte &= ~PTE_AR_MASK;
480                 if (!(res.pal_result[0] & 2))
481                         buf.pte &= ~PTE_PL_MASK;
482                 if (!(res.pal_result[0] & 4))
483                         buf.pte &= ~PTE_DIRTY;
484                 if (!(res.pal_result[0] & 8))
485                         buf.pte &= ~PTE_MA_MASK;
486                 sprintf(lbuf, "%03d %06x %013lx %013lx %4s %d  %d  %d  %d %d "
487                     "%-3s %d %06x\n", i, buf.rr.rr_rid, buf.ifa >> 12,
488                     (buf.pte & PTE_PPN_MASK) >> 12,
489                     psnames[(buf.itir & ITIR_PS_MASK) >> 2],
490                     (buf.pte & PTE_ED) ? 1 : 0,
491                     (int)(buf.pte & PTE_AR_MASK) >> 9,
492                     (int)(buf.pte & PTE_PL_MASK) >> 7,
493                     (buf.pte & PTE_DIRTY) ? 1 : 0,
494                     (buf.pte & PTE_ACCESSED) ? 1 : 0,
495                     manames[(buf.pte & PTE_MA_MASK) >> 2],
496                     (buf.pte & PTE_PRESENT) ? 1 : 0,
497                     (int)((buf.itir & ITIR_KEY_MASK) >> 8));
498                 pager_output(lbuf);
499         }
500         pager_close();
501
502         if (res.pal_status != 0) {
503                 printf("Error while getting TR contents\n");
504                 return CMD_ERROR;
505         }
506         return CMD_OK;
507 }
508
509 COMMAND_SET(itr, "itr", "print instruction TRs", command_itr);
510
511 static int
512 command_itr(int argc, char *argv[])
513 {
514         return print_trs(0);
515 }
516
517 COMMAND_SET(dtr, "dtr", "print data TRs", command_dtr);
518
519 static int
520 command_dtr(int argc, char *argv[])
521 {
522         return print_trs(1);
523 }
524
525 COMMAND_SET(hcdp, "hcdp", "Dump HCDP info", command_hcdp);
526
527 static char *
528 hcdp_string(char *s, u_int len)
529 {
530         static char buffer[256];
531
532         memcpy(buffer, s, len);
533         buffer[len] = 0;
534         return (buffer);
535 }
536         
537 static int
538 command_hcdp(int argc, char *argv[])
539 {
540         struct dig64_hcdp_table *tbl;
541         struct dig64_hcdp_entry *ent;
542         struct dig64_gas *gas;
543         int i;
544
545         tbl = efi_get_table(&hcdp);
546         if (tbl == NULL) {
547                 printf("No HCDP table present\n");
548                 return (CMD_OK);
549         }
550         if (memcmp(tbl->signature, HCDP_SIGNATURE, sizeof(tbl->signature))) {
551                 printf("HCDP table has invalid signature\n");
552                 return (CMD_OK);
553         }
554         if (tbl->length < sizeof(*tbl) - sizeof(*tbl->entry)) {
555                 printf("HCDP table too short\n");
556                 return (CMD_OK);
557         }
558         printf("HCDP table at 0x%016lx\n", (u_long)tbl);
559         printf("Signature  = %s\n", hcdp_string(tbl->signature, 4));
560         printf("Length     = %u\n", tbl->length);
561         printf("Revision   = %u\n", tbl->revision);
562         printf("Checksum   = %u\n", tbl->checksum);
563         printf("OEM Id     = %s\n", hcdp_string(tbl->oem_id, 6));
564         printf("Table Id   = %s\n", hcdp_string(tbl->oem_tbl_id, 8));
565         printf("OEM rev    = %u\n", tbl->oem_rev);
566         printf("Creator Id = %s\n", hcdp_string(tbl->creator_id, 4));
567         printf("Creator rev= %u\n", tbl->creator_rev);
568         printf("Entries    = %u\n", tbl->entries);
569         for (i = 0; i < tbl->entries; i++) {
570                 ent = tbl->entry + i;
571                 printf("Entry #%d:\n", i + 1);
572                 printf("    Type      = %u\n", ent->type);
573                 printf("    Databits  = %u\n", ent->databits);
574                 printf("    Parity    = %u\n", ent->parity);
575                 printf("    Stopbits  = %u\n", ent->stopbits);
576                 printf("    PCI seg   = %u\n", ent->pci_segment);
577                 printf("    PCI bus   = %u\n", ent->pci_bus);
578                 printf("    PCI dev   = %u\n", ent->pci_device);
579                 printf("    PCI func  = %u\n", ent->pci_function);
580                 printf("    Interrupt = %u\n", ent->interrupt);
581                 printf("    PCI flag  = %u\n", ent->pci_flag);
582                 printf("    Baudrate  = %lu\n",
583                     ((u_long)ent->baud_high << 32) + (u_long)ent->baud_low);
584                 gas = &ent->address;
585                 printf("    Addr space= %u\n", gas->addr_space);
586                 printf("    Bit width = %u\n", gas->bit_width);
587                 printf("    Bit offset= %u\n", gas->bit_offset);
588                 printf("    Address   = 0x%016lx\n",
589                     ((u_long)gas->addr_high << 32) + (u_long)gas->addr_low);
590                 printf("    PCI type  = %u\n", ent->pci_devid);
591                 printf("    PCI vndr  = %u\n", ent->pci_vendor);
592                 printf("    IRQ       = %u\n", ent->irq);
593                 printf("    PClock    = %u\n", ent->pclock);
594                 printf("    PCI iface = %u\n", ent->pci_interface);
595         }
596         printf("<EOT>\n");
597         return (CMD_OK);
598 }
599
600 COMMAND_SET(about, "about", "about the loader", command_about);
601
602 extern uint64_t _start_plabel[];
603
604 static int
605 command_about(int argc, char *argv[])
606 {
607         EFI_LOADED_IMAGE *img;
608
609         printf("%s\n", bootprog_name);
610         printf("revision %s\n", bootprog_rev);
611         printf("built by %s\n", bootprog_maker);
612         printf("built on %s\n", bootprog_date);
613
614         printf("\n");
615
616         BS->HandleProtocol(IH, &imgid, (VOID**)&img);
617         printf("image loaded at %p\n", img->ImageBase);
618         printf("entry at %#lx (%#lx)\n", _start_plabel[0], _start_plabel[1]);
619 }