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