]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/boot/ia64/efi/main.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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, &currdev.d_unit);
183         currdev.d_type = currdev.d_dev->dv_type;
184
185         env_setenv("loaddev", EV_VOLATILE, ia64_fmtdev(&currdev), env_noset,
186             env_nounset);
187
188         dev = get_dev_option(argc, argv);
189         if (dev == NULL)
190                 dev = ia64_fmtdev(&currdev);
191
192         env_setenv("currdev", EV_VOLATILE, dev, ia64_setcurrdev, env_nounset);
193
194         setenv("LINES", "24", 1);       /* optional */
195
196         archsw.arch_autoload = ia64_autoload;
197         archsw.arch_copyin = ia64_copyin;
198         archsw.arch_copyout = ia64_copyout;
199         archsw.arch_getdev = ia64_getdev;
200         archsw.arch_loadaddr = ia64_loadaddr;
201         archsw.arch_loadseg = ia64_loadseg;
202         archsw.arch_readin = ia64_readin;
203
204         interact();                     /* doesn't return */
205
206         return (EFI_SUCCESS);           /* keep compiler happy */
207 }
208
209 COMMAND_SET(quit, "quit", "exit the loader", command_quit);
210
211 static int
212 command_quit(int argc, char *argv[])
213 {
214         exit(0);
215         /* NOTREACHED */
216         return (CMD_OK);
217 }
218
219 COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
220  
221 static int
222 command_reboot(int argc, char *argv[])
223 {
224
225         RS->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
226         /* NOTREACHED */
227         return (CMD_OK);
228 }
229
230 COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
231
232 static int
233 command_memmap(int argc, char *argv[])
234 {
235         UINTN sz;
236         EFI_MEMORY_DESCRIPTOR *map, *p;
237         UINTN key, dsz;
238         UINT32 dver;
239         EFI_STATUS status;
240         int i, ndesc;
241         static char *types[] = {
242             "Reserved",
243             "LoaderCode",
244             "LoaderData",
245             "BootServicesCode",
246             "BootServicesData",
247             "RuntimeServicesCode",
248             "RuntimeServicesData",
249             "ConventionalMemory",
250             "UnusableMemory",
251             "ACPIReclaimMemory",
252             "ACPIMemoryNVS",
253             "MemoryMappedIO",
254             "MemoryMappedIOPortSpace",
255             "PalCode"
256         };
257
258         sz = 0;
259         status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
260         if (status != EFI_BUFFER_TOO_SMALL) {
261                 printf("Can't determine memory map size\n");
262                 return CMD_ERROR;
263         }
264         map = malloc(sz);
265         status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
266         if (EFI_ERROR(status)) {
267                 printf("Can't read memory map\n");
268                 return CMD_ERROR;
269         }
270
271         ndesc = sz / dsz;
272         printf("%23s %12s %12s %8s %4s\n",
273                "Type", "Physical", "Virtual", "#Pages", "Attr");
274                
275         for (i = 0, p = map; i < ndesc;
276              i++, p = NextMemoryDescriptor(p, dsz)) {
277             printf("%23s %012lx %012lx %08lx ",
278                    types[p->Type],
279                    p->PhysicalStart,
280                    p->VirtualStart,
281                    p->NumberOfPages);
282             if (p->Attribute & EFI_MEMORY_UC)
283                 printf("UC ");
284             if (p->Attribute & EFI_MEMORY_WC)
285                 printf("WC ");
286             if (p->Attribute & EFI_MEMORY_WT)
287                 printf("WT ");
288             if (p->Attribute & EFI_MEMORY_WB)
289                 printf("WB ");
290             if (p->Attribute & EFI_MEMORY_UCE)
291                 printf("UCE ");
292             if (p->Attribute & EFI_MEMORY_WP)
293                 printf("WP ");
294             if (p->Attribute & EFI_MEMORY_RP)
295                 printf("RP ");
296             if (p->Attribute & EFI_MEMORY_XP)
297                 printf("XP ");
298             if (p->Attribute & EFI_MEMORY_RUNTIME)
299                 printf("RUNTIME");
300             printf("\n");
301         }
302
303         return CMD_OK;
304 }
305
306 COMMAND_SET(configuration, "configuration",
307             "print configuration tables", command_configuration);
308
309 static const char *
310 guid_to_string(EFI_GUID *guid)
311 {
312         static char buf[40];
313
314         sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
315             guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
316             guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
317             guid->Data4[5], guid->Data4[6], guid->Data4[7]);
318         return (buf);
319 }
320
321 static int
322 command_configuration(int argc, char *argv[])
323 {
324         int i;
325
326         printf("NumberOfTableEntries=%ld\n", ST->NumberOfTableEntries);
327         for (i = 0; i < ST->NumberOfTableEntries; i++) {
328                 EFI_GUID *guid;
329
330                 printf("  ");
331                 guid = &ST->ConfigurationTable[i].VendorGuid;
332                 if (!memcmp(guid, &mps, sizeof(EFI_GUID)))
333                         printf("MPS Table");
334                 else if (!memcmp(guid, &acpi, sizeof(EFI_GUID)))
335                         printf("ACPI Table");
336                 else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID)))
337                         printf("ACPI 2.0 Table");
338                 else if (!memcmp(guid, &smbios, sizeof(EFI_GUID)))
339                         printf("SMBIOS Table");
340                 else if (!memcmp(guid, &sal, sizeof(EFI_GUID)))
341                         printf("SAL System Table");
342                 else if (!memcmp(guid, &hcdp, sizeof(EFI_GUID)))
343                         printf("DIG64 HCDP Table");
344                 else
345                         printf("Unknown Table (%s)", guid_to_string(guid));
346                 printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
347         }
348
349         return CMD_OK;
350 }    
351
352 COMMAND_SET(sal, "sal", "print SAL System Table", command_sal);
353
354 static int
355 command_sal(int argc, char *argv[])
356 {
357         int i;
358         struct sal_system_table *saltab = 0;
359         static int sizes[6] = {
360                 48, 32, 16, 32, 16, 16
361         };
362         u_int8_t *p;
363
364         saltab = efi_get_table(&sal);
365         if (saltab == NULL) {
366                 printf("Can't find SAL System Table\n");
367                 return CMD_ERROR;
368         }
369
370         if (memcmp(saltab->sal_signature, "SST_", 4)) {
371                 printf("Bad signature for SAL System Table\n");
372                 return CMD_ERROR;
373         }
374
375         printf("SAL Revision %x.%02x\n",
376                saltab->sal_rev[1],
377                saltab->sal_rev[0]);
378         printf("SAL A Version %x.%02x\n",
379                saltab->sal_a_version[1],
380                saltab->sal_a_version[0]);
381         printf("SAL B Version %x.%02x\n",
382                saltab->sal_b_version[1],
383                saltab->sal_b_version[0]);
384
385         p = (u_int8_t *) (saltab + 1);
386         for (i = 0; i < saltab->sal_entry_count; i++) {
387                 printf("  Desc %d", *p);
388                 if (*p == 0) {
389                         struct sal_entrypoint_descriptor *dp;
390                         dp = (struct sal_entrypoint_descriptor *) p;
391                         printf("\n");
392                         printf("    PAL Proc at 0x%lx\n",
393                                dp->sale_pal_proc);
394                         printf("    SAL Proc at 0x%lx\n",
395                                dp->sale_sal_proc);
396                         printf("    SAL GP at 0x%lx\n",
397                                dp->sale_sal_gp);
398                 } else if (*p == 1) {
399                         struct sal_memory_descriptor *dp;
400                         dp = (struct sal_memory_descriptor *) p;
401                         printf(" Type %d.%d, ",
402                                dp->sale_memory_type[0],
403                                dp->sale_memory_type[1]);
404                         printf("Address 0x%lx, ",
405                                dp->sale_physical_address);
406                         printf("Length 0x%x\n",
407                                dp->sale_length);
408                 } else if (*p == 5) {
409                         struct sal_ap_wakeup_descriptor *dp;
410                         dp = (struct sal_ap_wakeup_descriptor *) p;
411                         printf("\n");
412                         printf("    Mechanism %d\n", dp->sale_mechanism);
413                         printf("    Vector 0x%lx\n", dp->sale_vector);
414                 } else
415                         printf("\n");
416
417                 p += sizes[*p];
418         }
419
420         return CMD_OK;
421 }
422
423 int
424 print_trs(int type)
425 {
426         struct ia64_pal_result res;
427         int i, maxtr;
428         struct {
429                 pt_entry_t      pte;
430                 uint64_t        itir;
431                 uint64_t        ifa;
432                 struct ia64_rr  rr;
433         } buf;
434         static const char *psnames[] = {
435                 "1B",   "2B",   "4B",   "8B",
436                 "16B",  "32B",  "64B",  "128B",
437                 "256B", "512B", "1K",   "2K",
438                 "4K",   "8K",   "16K",  "32K",
439                 "64K",  "128K", "256K", "512K",
440                 "1M",   "2M",   "4M",   "8M",
441                 "16M",  "32M",  "64M",  "128M",
442                 "256M", "512M", "1G",   "2G"
443         };
444         static const char *manames[] = {
445                 "WB",   "bad",  "bad",  "bad",
446                 "UC",   "UCE",  "WC",   "NaT",
447         };
448
449         res = ia64_call_pal_static(PAL_VM_SUMMARY, 0, 0, 0);
450         if (res.pal_status != 0) {
451                 printf("Can't get VM summary\n");
452                 return CMD_ERROR;
453         }
454
455         if (type == 0)
456                 maxtr = (res.pal_result[0] >> 40) & 0xff;
457         else
458                 maxtr = (res.pal_result[0] >> 32) & 0xff;
459
460         printf("%d translation registers\n", maxtr);
461
462         pager_open();
463         pager_output("TR# RID    Virtual Page  Physical Page PgSz ED AR PL D A MA  P KEY\n");
464         for (i = 0; i <= maxtr; i++) {
465                 char lbuf[128];
466
467                 bzero(&buf, sizeof(buf));
468                 res = ia64_call_pal_stacked(PAL_VM_TR_READ, i, type,
469                                             (u_int64_t) &buf);
470                 if (res.pal_status != 0)
471                         break;
472
473                 /* Only display valid translations */
474                 if ((buf.ifa & 1) == 0)
475                         continue;
476
477                 if (!(res.pal_result[0] & 1))
478                         buf.pte &= ~PTE_AR_MASK;
479                 if (!(res.pal_result[0] & 2))
480                         buf.pte &= ~PTE_PL_MASK;
481                 if (!(res.pal_result[0] & 4))
482                         buf.pte &= ~PTE_DIRTY;
483                 if (!(res.pal_result[0] & 8))
484                         buf.pte &= ~PTE_MA_MASK;
485                 sprintf(lbuf, "%03d %06x %013lx %013lx %4s %d  %d  %d  %d %d "
486                     "%-3s %d %06x\n", i, buf.rr.rr_rid, buf.ifa >> 12,
487                     (buf.pte & PTE_PPN_MASK) >> 12,
488                     psnames[(buf.itir & ITIR_PS_MASK) >> 2],
489                     (buf.pte & PTE_ED) ? 1 : 0,
490                     (int)(buf.pte & PTE_AR_MASK) >> 9,
491                     (int)(buf.pte & PTE_PL_MASK) >> 7,
492                     (buf.pte & PTE_DIRTY) ? 1 : 0,
493                     (buf.pte & PTE_ACCESSED) ? 1 : 0,
494                     manames[(buf.pte & PTE_MA_MASK) >> 2],
495                     (buf.pte & PTE_PRESENT) ? 1 : 0,
496                     (int)((buf.itir & ITIR_KEY_MASK) >> 8));
497                 pager_output(lbuf);
498         }
499         pager_close();
500
501         if (res.pal_status != 0) {
502                 printf("Error while getting TR contents\n");
503                 return CMD_ERROR;
504         }
505         return CMD_OK;
506 }
507
508 COMMAND_SET(itr, "itr", "print instruction TRs", command_itr);
509
510 static int
511 command_itr(int argc, char *argv[])
512 {
513         return print_trs(0);
514 }
515
516 COMMAND_SET(dtr, "dtr", "print data TRs", command_dtr);
517
518 static int
519 command_dtr(int argc, char *argv[])
520 {
521         return print_trs(1);
522 }
523
524 COMMAND_SET(hcdp, "hcdp", "Dump HCDP info", command_hcdp);
525
526 static char *
527 hcdp_string(char *s, u_int len)
528 {
529         static char buffer[256];
530
531         memcpy(buffer, s, len);
532         buffer[len] = 0;
533         return (buffer);
534 }
535         
536 static int
537 command_hcdp(int argc, char *argv[])
538 {
539         struct dig64_hcdp_table *tbl;
540         struct dig64_hcdp_entry *ent;
541         struct dig64_gas *gas;
542         int i;
543
544         tbl = efi_get_table(&hcdp);
545         if (tbl == NULL) {
546                 printf("No HCDP table present\n");
547                 return (CMD_OK);
548         }
549         if (memcmp(tbl->signature, HCDP_SIGNATURE, sizeof(tbl->signature))) {
550                 printf("HCDP table has invalid signature\n");
551                 return (CMD_OK);
552         }
553         if (tbl->length < sizeof(*tbl) - sizeof(*tbl->entry)) {
554                 printf("HCDP table too short\n");
555                 return (CMD_OK);
556         }
557         printf("HCDP table at 0x%016lx\n", (u_long)tbl);
558         printf("Signature  = %s\n", hcdp_string(tbl->signature, 4));
559         printf("Length     = %u\n", tbl->length);
560         printf("Revision   = %u\n", tbl->revision);
561         printf("Checksum   = %u\n", tbl->checksum);
562         printf("OEM Id     = %s\n", hcdp_string(tbl->oem_id, 6));
563         printf("Table Id   = %s\n", hcdp_string(tbl->oem_tbl_id, 8));
564         printf("OEM rev    = %u\n", tbl->oem_rev);
565         printf("Creator Id = %s\n", hcdp_string(tbl->creator_id, 4));
566         printf("Creator rev= %u\n", tbl->creator_rev);
567         printf("Entries    = %u\n", tbl->entries);
568         for (i = 0; i < tbl->entries; i++) {
569                 ent = tbl->entry + i;
570                 printf("Entry #%d:\n", i + 1);
571                 printf("    Type      = %u\n", ent->type);
572                 printf("    Databits  = %u\n", ent->databits);
573                 printf("    Parity    = %u\n", ent->parity);
574                 printf("    Stopbits  = %u\n", ent->stopbits);
575                 printf("    PCI seg   = %u\n", ent->pci_segment);
576                 printf("    PCI bus   = %u\n", ent->pci_bus);
577                 printf("    PCI dev   = %u\n", ent->pci_device);
578                 printf("    PCI func  = %u\n", ent->pci_function);
579                 printf("    Interrupt = %u\n", ent->interrupt);
580                 printf("    PCI flag  = %u\n", ent->pci_flag);
581                 printf("    Baudrate  = %lu\n",
582                     ((u_long)ent->baud_high << 32) + (u_long)ent->baud_low);
583                 gas = &ent->address;
584                 printf("    Addr space= %u\n", gas->addr_space);
585                 printf("    Bit width = %u\n", gas->bit_width);
586                 printf("    Bit offset= %u\n", gas->bit_offset);
587                 printf("    Address   = 0x%016lx\n",
588                     ((u_long)gas->addr_high << 32) + (u_long)gas->addr_low);
589                 printf("    PCI type  = %u\n", ent->pci_devid);
590                 printf("    PCI vndr  = %u\n", ent->pci_vendor);
591                 printf("    IRQ       = %u\n", ent->irq);
592                 printf("    PClock    = %u\n", ent->pclock);
593                 printf("    PCI iface = %u\n", ent->pci_interface);
594         }
595         printf("<EOT>\n");
596         return (CMD_OK);
597 }
598
599 COMMAND_SET(about, "about", "about the loader", command_about);
600
601 extern uint64_t _start_plabel[];
602
603 static int
604 command_about(int argc, char *argv[])
605 {
606         EFI_LOADED_IMAGE *img;
607
608         printf("%s\n", bootprog_name);
609         printf("revision %s\n", bootprog_rev);
610         printf("built by %s\n", bootprog_maker);
611         printf("built on %s\n", bootprog_date);
612
613         printf("\n");
614
615         BS->HandleProtocol(IH, &imgid, (VOID**)&img);
616         printf("image loaded at %p\n", img->ImageBase);
617         printf("entry at %#lx (%#lx)\n", _start_plabel[0], _start_plabel[1]);
618 }