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