]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/boot/ia64/efi/main.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.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 "bootstrap.h"
43 #include "efiboot.h"
44
45 extern char bootprog_name[];
46 extern char bootprog_rev[];
47 extern char bootprog_date[];
48 extern char bootprog_maker[];
49
50 struct efi_devdesc      currdev;        /* our current device */
51 struct arch_switch      archsw;         /* MI/MD interface boundary */
52
53 extern u_int64_t        ia64_pal_entry;
54
55 EFI_GUID acpi = ACPI_TABLE_GUID;
56 EFI_GUID acpi20 = ACPI_20_TABLE_GUID;
57 EFI_GUID devid = DEVICE_PATH_PROTOCOL;
58 EFI_GUID hcdp = HCDP_TABLE_GUID;
59 EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
60 EFI_GUID mps = MPS_TABLE_GUID;
61 EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL;
62 EFI_GUID sal = SAL_SYSTEM_TABLE_GUID;
63 EFI_GUID smbios = SMBIOS_TABLE_GUID;
64
65 static void
66 find_pal_proc(void)
67 {
68         int i;
69         struct sal_system_table *saltab = 0;
70         static int sizes[6] = {
71                 48, 32, 16, 32, 16, 16
72         };
73         u_int8_t *p;
74
75         saltab = efi_get_table(&sal);
76         if (saltab == NULL) {
77                 printf("Can't find SAL System Table\n");
78                 return;
79         }
80
81         if (memcmp(saltab->sal_signature, "SST_", 4)) {
82                 printf("Bad signature for SAL System Table\n");
83                 return;
84         }
85
86         p = (u_int8_t *) (saltab + 1);
87         for (i = 0; i < saltab->sal_entry_count; i++) {
88                 if (*p == 0) {
89                         struct sal_entrypoint_descriptor *dp;
90                         dp = (struct sal_entrypoint_descriptor *) p;
91                         ia64_pal_entry = dp->sale_pal_proc;
92                         return;
93                 }
94                 p += sizes[*p];
95         }
96
97         printf("Can't find PAL proc\n");
98         return;
99 }
100
101 EFI_STATUS
102 main(int argc, CHAR16 *argv[])
103 {
104         EFI_LOADED_IMAGE *img;
105         int i;
106
107         /* 
108          * XXX Chicken-and-egg problem; we want to have console output
109          * early, but some console attributes may depend on reading from
110          * eg. the boot device, which we can't do yet.  We can use
111          * printf() etc. once this is done.
112          */
113         cons_probe();
114
115         /*
116          * Initialise the block cache
117          */
118         bcache_init(32, 512);           /* 16k XXX tune this */
119
120         find_pal_proc();
121
122         /*
123          * March through the device switch probing for things.
124          */
125         for (i = 0; devsw[i] != NULL; i++)
126                 if (devsw[i]->dv_init != NULL)
127                         (devsw[i]->dv_init)();
128
129         efinet_init_driver();
130
131         /* Get our loaded image protocol interface structure. */
132         BS->HandleProtocol(IH, &imgid, (VOID**)&img);
133
134         printf("Image base: 0x%016lx\n", (u_long)img->ImageBase);
135
136         printf("\n");
137         printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
138         printf("(%s, %s)\n", bootprog_maker, bootprog_date);
139
140         i = efifs_get_unit(img->DeviceHandle);
141         if (i >= 0) {
142                 currdev.d_dev = devsw[0];               /* XXX disk */
143                 currdev.d_kind.efidisk.unit = i;
144                 /* XXX should be able to detect this, default to autoprobe */
145                 currdev.d_kind.efidisk.slice = -1;
146                 currdev.d_kind.efidisk.partition = 0;
147         } else {
148                 currdev.d_dev = devsw[1];               /* XXX net */
149                 currdev.d_kind.netif.unit = 0;          /* XXX */
150         }
151         currdev.d_type = currdev.d_dev->dv_type;
152
153         /*
154          * Disable the watchdog timer. By default the boot manager sets
155          * the timer to 5 minutes before invoking a boot option. If we
156          * want to return to the boot manager, we have to disable the
157          * watchdog timer and since we're an interactive program, we don't
158          * want to wait until the user types "quit". The timer may have
159          * fired by then. We don't care if this fails. It does not prevent
160          * normal functioning in any way...
161          */
162         BS->SetWatchdogTimer(0, 0, 0, NULL);
163
164         env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
165             efi_setcurrdev, env_nounset);
166         env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
167             env_nounset);
168
169         setenv("LINES", "24", 1);       /* optional */
170     
171         archsw.arch_autoload = efi_autoload;
172         archsw.arch_getdev = efi_getdev;
173         archsw.arch_copyin = efi_copyin;
174         archsw.arch_copyout = efi_copyout;
175         archsw.arch_readin = efi_readin;
176
177         interact();                     /* doesn't return */
178
179         return (EFI_SUCCESS);           /* keep compiler happy */
180 }
181
182 COMMAND_SET(quit, "quit", "exit the loader", command_quit);
183
184 static int
185 command_quit(int argc, char *argv[])
186 {
187         exit(0);
188         return (CMD_OK);
189 }
190
191 COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
192
193 static int
194 command_memmap(int argc, char *argv[])
195 {
196         UINTN sz;
197         EFI_MEMORY_DESCRIPTOR *map, *p;
198         UINTN key, dsz;
199         UINT32 dver;
200         EFI_STATUS status;
201         int i, ndesc;
202         static char *types[] = {
203             "Reserved",
204             "LoaderCode",
205             "LoaderData",
206             "BootServicesCode",
207             "BootServicesData",
208             "RuntimeServicesCode",
209             "RuntimeServicesData",
210             "ConventionalMemory",
211             "UnusableMemory",
212             "ACPIReclaimMemory",
213             "ACPIMemoryNVS",
214             "MemoryMappedIO",
215             "MemoryMappedIOPortSpace",
216             "PalCode"
217         };
218
219         sz = 0;
220         status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
221         if (status != EFI_BUFFER_TOO_SMALL) {
222                 printf("Can't determine memory map size\n");
223                 return CMD_ERROR;
224         }
225         map = malloc(sz);
226         status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
227         if (EFI_ERROR(status)) {
228                 printf("Can't read memory map\n");
229                 return CMD_ERROR;
230         }
231
232         ndesc = sz / dsz;
233         printf("%23s %12s %12s %8s %4s\n",
234                "Type", "Physical", "Virtual", "#Pages", "Attr");
235                
236         for (i = 0, p = map; i < ndesc;
237              i++, p = NextMemoryDescriptor(p, dsz)) {
238             printf("%23s %012lx %012lx %08lx ",
239                    types[p->Type],
240                    p->PhysicalStart,
241                    p->VirtualStart,
242                    p->NumberOfPages);
243             if (p->Attribute & EFI_MEMORY_UC)
244                 printf("UC ");
245             if (p->Attribute & EFI_MEMORY_WC)
246                 printf("WC ");
247             if (p->Attribute & EFI_MEMORY_WT)
248                 printf("WT ");
249             if (p->Attribute & EFI_MEMORY_WB)
250                 printf("WB ");
251             if (p->Attribute & EFI_MEMORY_UCE)
252                 printf("UCE ");
253             if (p->Attribute & EFI_MEMORY_WP)
254                 printf("WP ");
255             if (p->Attribute & EFI_MEMORY_RP)
256                 printf("RP ");
257             if (p->Attribute & EFI_MEMORY_XP)
258                 printf("XP ");
259             if (p->Attribute & EFI_MEMORY_RUNTIME)
260                 printf("RUNTIME");
261             printf("\n");
262         }
263
264         return CMD_OK;
265 }
266
267 COMMAND_SET(configuration, "configuration",
268             "print configuration tables", command_configuration);
269
270 static const char *
271 guid_to_string(EFI_GUID *guid)
272 {
273         static char buf[40];
274
275         sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
276             guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
277             guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
278             guid->Data4[5], guid->Data4[6], guid->Data4[7]);
279         return (buf);
280 }
281
282 static int
283 command_configuration(int argc, char *argv[])
284 {
285         int i;
286
287         printf("NumberOfTableEntries=%ld\n", ST->NumberOfTableEntries);
288         for (i = 0; i < ST->NumberOfTableEntries; i++) {
289                 EFI_GUID *guid;
290
291                 printf("  ");
292                 guid = &ST->ConfigurationTable[i].VendorGuid;
293                 if (!memcmp(guid, &mps, sizeof(EFI_GUID)))
294                         printf("MPS Table");
295                 else if (!memcmp(guid, &acpi, sizeof(EFI_GUID)))
296                         printf("ACPI Table");
297                 else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID)))
298                         printf("ACPI 2.0 Table");
299                 else if (!memcmp(guid, &smbios, sizeof(EFI_GUID)))
300                         printf("SMBIOS Table");
301                 else if (!memcmp(guid, &sal, sizeof(EFI_GUID)))
302                         printf("SAL System Table");
303                 else if (!memcmp(guid, &hcdp, sizeof(EFI_GUID)))
304                         printf("DIG64 HCDP Table");
305                 else
306                         printf("Unknown Table (%s)", guid_to_string(guid));
307                 printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
308         }
309
310         return CMD_OK;
311 }    
312
313 COMMAND_SET(sal, "sal", "print SAL System Table", command_sal);
314
315 static int
316 command_sal(int argc, char *argv[])
317 {
318         int i;
319         struct sal_system_table *saltab = 0;
320         static int sizes[6] = {
321                 48, 32, 16, 32, 16, 16
322         };
323         u_int8_t *p;
324
325         saltab = efi_get_table(&sal);
326         if (saltab == NULL) {
327                 printf("Can't find SAL System Table\n");
328                 return CMD_ERROR;
329         }
330
331         if (memcmp(saltab->sal_signature, "SST_", 4)) {
332                 printf("Bad signature for SAL System Table\n");
333                 return CMD_ERROR;
334         }
335
336         printf("SAL Revision %x.%02x\n",
337                saltab->sal_rev[1],
338                saltab->sal_rev[0]);
339         printf("SAL A Version %x.%02x\n",
340                saltab->sal_a_version[1],
341                saltab->sal_a_version[0]);
342         printf("SAL B Version %x.%02x\n",
343                saltab->sal_b_version[1],
344                saltab->sal_b_version[0]);
345
346         p = (u_int8_t *) (saltab + 1);
347         for (i = 0; i < saltab->sal_entry_count; i++) {
348                 printf("  Desc %d", *p);
349                 if (*p == 0) {
350                         struct sal_entrypoint_descriptor *dp;
351                         dp = (struct sal_entrypoint_descriptor *) p;
352                         printf("\n");
353                         printf("    PAL Proc at 0x%lx\n",
354                                dp->sale_pal_proc);
355                         printf("    SAL Proc at 0x%lx\n",
356                                dp->sale_sal_proc);
357                         printf("    SAL GP at 0x%lx\n",
358                                dp->sale_sal_gp);
359                 } else if (*p == 1) {
360                         struct sal_memory_descriptor *dp;
361                         dp = (struct sal_memory_descriptor *) p;
362                         printf(" Type %d.%d, ",
363                                dp->sale_memory_type[0],
364                                dp->sale_memory_type[1]);
365                         printf("Address 0x%lx, ",
366                                dp->sale_physical_address);
367                         printf("Length 0x%x\n",
368                                dp->sale_length);
369                 } else if (*p == 5) {
370                         struct sal_ap_wakeup_descriptor *dp;
371                         dp = (struct sal_ap_wakeup_descriptor *) p;
372                         printf("\n");
373                         printf("    Mechanism %d\n", dp->sale_mechanism);
374                         printf("    Vector 0x%lx\n", dp->sale_vector);
375                 } else
376                         printf("\n");
377
378                 p += sizes[*p];
379         }
380
381         return CMD_OK;
382 }
383
384 int
385 print_trs(int type)
386 {
387         struct ia64_pal_result res;
388         int i, maxtr;
389         struct {
390                 pt_entry_t      pte;
391                 uint64_t        itir;
392                 uint64_t        ifa;
393                 struct ia64_rr  rr;
394         } buf;
395         static const char *psnames[] = {
396                 "1B",   "2B",   "4B",   "8B",
397                 "16B",  "32B",  "64B",  "128B",
398                 "256B", "512B", "1K",   "2K",
399                 "4K",   "8K",   "16K",  "32K",
400                 "64K",  "128K", "256K", "512K",
401                 "1M",   "2M",   "4M",   "8M",
402                 "16M",  "32M",  "64M",  "128M",
403                 "256M", "512M", "1G",   "2G"
404         };
405         static const char *manames[] = {
406                 "WB",   "bad",  "bad",  "bad",
407                 "UC",   "UCE",  "WC",   "NaT",
408         };
409
410         res = ia64_call_pal_static(PAL_VM_SUMMARY, 0, 0, 0);
411         if (res.pal_status != 0) {
412                 printf("Can't get VM summary\n");
413                 return CMD_ERROR;
414         }
415
416         if (type == 0)
417                 maxtr = (res.pal_result[0] >> 40) & 0xff;
418         else
419                 maxtr = (res.pal_result[0] >> 32) & 0xff;
420
421         printf("%d translation registers\n", maxtr);
422
423         pager_open();
424         pager_output("TR# RID    Virtual Page  Physical Page PgSz ED AR PL D A MA  P KEY\n");
425         for (i = 0; i <= maxtr; i++) {
426                 char lbuf[128];
427
428                 bzero(&buf, sizeof(buf));
429                 res = ia64_call_pal_stacked(PAL_VM_TR_READ, i, type,
430                                             (u_int64_t) &buf);
431                 if (res.pal_status != 0)
432                         break;
433
434                 /* Only display valid translations */
435                 if ((buf.ifa & 1) == 0)
436                         continue;
437
438                 if (!(res.pal_result[0] & 1))
439                         buf.pte &= ~PTE_AR_MASK;
440                 if (!(res.pal_result[0] & 2))
441                         buf.pte &= ~PTE_PL_MASK;
442                 if (!(res.pal_result[0] & 4))
443                         buf.pte &= ~PTE_DIRTY;
444                 if (!(res.pal_result[0] & 8))
445                         buf.pte &= ~PTE_MA_MASK;
446                 sprintf(lbuf, "%03d %06x %013lx %013lx %4s %d  %d  %d  %d %d "
447                     "%-3s %d %06x\n", i, buf.rr.rr_rid, buf.ifa >> 12,
448                     (buf.pte & PTE_PPN_MASK) >> 12,
449                     psnames[(buf.itir & ITIR_PS_MASK) >> 2],
450                     (buf.pte & PTE_ED) ? 1 : 0,
451                     (int)(buf.pte & PTE_AR_MASK) >> 9,
452                     (int)(buf.pte & PTE_PL_MASK) >> 7,
453                     (buf.pte & PTE_DIRTY) ? 1 : 0,
454                     (buf.pte & PTE_ACCESSED) ? 1 : 0,
455                     manames[(buf.pte & PTE_MA_MASK) >> 2],
456                     (buf.pte & PTE_PRESENT) ? 1 : 0,
457                     (int)((buf.itir & ITIR_KEY_MASK) >> 8));
458                 pager_output(lbuf);
459         }
460         pager_close();
461
462         if (res.pal_status != 0) {
463                 printf("Error while getting TR contents\n");
464                 return CMD_ERROR;
465         }
466         return CMD_OK;
467 }
468
469 COMMAND_SET(itr, "itr", "print instruction TRs", command_itr);
470
471 static int
472 command_itr(int argc, char *argv[])
473 {
474         return print_trs(0);
475 }
476
477 COMMAND_SET(dtr, "dtr", "print data TRs", command_dtr);
478
479 static int
480 command_dtr(int argc, char *argv[])
481 {
482         return print_trs(1);
483 }
484
485 COMMAND_SET(hcdp, "hcdp", "Dump HCDP info", command_hcdp);
486
487 static char *
488 hcdp_string(char *s, u_int len)
489 {
490         static char buffer[256];
491
492         memcpy(buffer, s, len);
493         buffer[len] = 0;
494         return (buffer);
495 }
496         
497 static int
498 command_hcdp(int argc, char *argv[])
499 {
500         struct dig64_hcdp_table *tbl;
501         struct dig64_hcdp_entry *ent;
502         struct dig64_gas *gas;
503         int i;
504
505         tbl = efi_get_table(&hcdp);
506         if (tbl == NULL) {
507                 printf("No HCDP table present\n");
508                 return (CMD_OK);
509         }
510         if (memcmp(tbl->signature, HCDP_SIGNATURE, sizeof(tbl->signature))) {
511                 printf("HCDP table has invalid signature\n");
512                 return (CMD_OK);
513         }
514         if (tbl->length < sizeof(*tbl) - sizeof(*tbl->entry)) {
515                 printf("HCDP table too short\n");
516                 return (CMD_OK);
517         }
518         printf("HCDP table at 0x%016lx\n", (u_long)tbl);
519         printf("Signature  = %s\n", hcdp_string(tbl->signature, 4));
520         printf("Length     = %u\n", tbl->length);
521         printf("Revision   = %u\n", tbl->revision);
522         printf("Checksum   = %u\n", tbl->checksum);
523         printf("OEM Id     = %s\n", hcdp_string(tbl->oem_id, 6));
524         printf("Table Id   = %s\n", hcdp_string(tbl->oem_tbl_id, 8));
525         printf("OEM rev    = %u\n", tbl->oem_rev);
526         printf("Creator Id = %s\n", hcdp_string(tbl->creator_id, 4));
527         printf("Creator rev= %u\n", tbl->creator_rev);
528         printf("Entries    = %u\n", tbl->entries);
529         for (i = 0; i < tbl->entries; i++) {
530                 ent = tbl->entry + i;
531                 printf("Entry #%d:\n", i + 1);
532                 printf("    Type      = %u\n", ent->type);
533                 printf("    Databits  = %u\n", ent->databits);
534                 printf("    Parity    = %u\n", ent->parity);
535                 printf("    Stopbits  = %u\n", ent->stopbits);
536                 printf("    PCI seg   = %u\n", ent->pci_segment);
537                 printf("    PCI bus   = %u\n", ent->pci_bus);
538                 printf("    PCI dev   = %u\n", ent->pci_device);
539                 printf("    PCI func  = %u\n", ent->pci_function);
540                 printf("    Interrupt = %u\n", ent->interrupt);
541                 printf("    PCI flag  = %u\n", ent->pci_flag);
542                 printf("    Baudrate  = %lu\n",
543                     ((u_long)ent->baud_high << 32) + (u_long)ent->baud_low);
544                 gas = &ent->address;
545                 printf("    Addr space= %u\n", gas->addr_space);
546                 printf("    Bit width = %u\n", gas->bit_width);
547                 printf("    Bit offset= %u\n", gas->bit_offset);
548                 printf("    Address   = 0x%016lx\n",
549                     ((u_long)gas->addr_high << 32) + (u_long)gas->addr_low);
550                 printf("    PCI type  = %u\n", ent->pci_devid);
551                 printf("    PCI vndr  = %u\n", ent->pci_vendor);
552                 printf("    IRQ       = %u\n", ent->irq);
553                 printf("    PClock    = %u\n", ent->pclock);
554                 printf("    PCI iface = %u\n", ent->pci_interface);
555         }
556         printf("<EOT>\n");
557         return (CMD_OK);
558 }