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