main.c revision 107722
1116576Smurray/*- 2116576Smurray * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3116576Smurray * Copyright (c) 1998,2000 Doug Rabson <dfr@freebsd.org> 4116576Smurray * All rights reserved. 5116576Smurray * 6116576Smurray * Redistribution and use in source and binary forms, with or without 7116576Smurray * modification, are permitted provided that the following conditions 8116576Smurray * are met: 9116576Smurray * 1. Redistributions of source code must retain the above copyright 10116576Smurray * notice, this list of conditions and the following disclaimer. 11116576Smurray * 2. Redistributions in binary form must reproduce the above copyright 12116576Smurray * notice, this list of conditions and the following disclaimer in the 13116576Smurray * documentation and/or other materials provided with the distribution. 14116576Smurray * 15116576Smurray * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16116576Smurray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17116576Smurray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18116576Smurray * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19116576Smurray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20116576Smurray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21116576Smurray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22116576Smurray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23116576Smurray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24116576Smurray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25116576Smurray * SUCH DAMAGE. 26116576Smurray */ 27116576Smurray 28116576Smurray#ifndef lint 29116576Smurraystatic const char rcsid[] = 30116576Smurray "$FreeBSD: head/sys/boot/ia64/efi/main.c 107722 2002-12-10 04:55:25Z marcel $"; 31116576Smurray#endif /* not lint */ 32116576Smurray 33116576Smurray#include <stand.h> 34116576Smurray#include <string.h> 35116576Smurray#include <setjmp.h> 36116576Smurray#include <machine/sal.h> 37116576Smurray#include <machine/pal.h> 38116576Smurray#include <machine/pte.h> 39116576Smurray 40116576Smurray#include <efi.h> 41116576Smurray#include <efilib.h> 42116576Smurray 43116576Smurray#include "bootstrap.h" 44116576Smurray#include "efiboot.h" 45116576Smurray 46116576Smurrayextern char bootprog_name[]; 47116576Smurrayextern char bootprog_rev[]; 48116576Smurrayextern char bootprog_date[]; 49116576Smurrayextern char bootprog_maker[]; 50116576Smurray 51116576Smurraystruct efi_devdesc currdev; /* our current device */ 52116576Smurraystruct arch_switch archsw; /* MI/MD interface boundary */ 53116576Smurray 54116576Smurrayextern u_int64_t ia64_pal_entry; 55116576Smurray 56116576SmurrayEFI_GUID acpi = ACPI_TABLE_GUID; 57116576SmurrayEFI_GUID acpi20 = ACPI_20_TABLE_GUID; 58116576SmurrayEFI_GUID hcdp = HCDP_TABLE_GUID; 59116576SmurrayEFI_GUID imgid = LOADED_IMAGE_PROTOCOL; 60116576SmurrayEFI_GUID mps = MPS_TABLE_GUID; 61116576SmurrayEFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL; 62116576SmurrayEFI_GUID sal = SAL_SYSTEM_TABLE_GUID; 63116576SmurrayEFI_GUID smbios = SMBIOS_TABLE_GUID; 64116576Smurray 65116576Smurraystatic void 66116576Smurrayfind_pal_proc(void) 67116576Smurray{ 68116576Smurray int i; 69116576Smurray struct sal_system_table *saltab = 0; 70116576Smurray static int sizes[6] = { 71116576Smurray 48, 32, 16, 32, 16, 16 72116576Smurray }; 73116576Smurray u_int8_t *p; 74116576Smurray 75116576Smurray for (i = 0; i < ST->NumberOfTableEntries; i++) { 76116576Smurray if (!memcmp(&ST->ConfigurationTable[i].VendorGuid, 77116576Smurray &sal, sizeof(EFI_GUID))) 78116576Smurray saltab = ST->ConfigurationTable[i].VendorTable; 79116576Smurray } 80116576Smurray 81116576Smurray if (!saltab) { 82116576Smurray printf("Can't find SAL System Table\n"); 83116576Smurray return; 84116576Smurray } 85116576Smurray 86116576Smurray if (memcmp(saltab->sal_signature, "SST_", 4)) { 87116576Smurray printf("Bad signature for SAL System Table\n"); 88116576Smurray return; 89116576Smurray } 90116576Smurray 91116576Smurray p = (u_int8_t *) (saltab + 1); 92116576Smurray for (i = 0; i < saltab->sal_entry_count; i++) { 93116576Smurray if (*p == 0) { 94116576Smurray struct sal_entrypoint_descriptor *dp; 95116576Smurray dp = (struct sal_entrypoint_descriptor *) p; 96116576Smurray ia64_pal_entry = dp->sale_pal_proc; 97116576Smurray return; 98116576Smurray } 99116576Smurray p += sizes[*p]; 100116576Smurray } 101116576Smurray 102116576Smurray printf("Can't find PAL proc\n"); 103116576Smurray return; 104116576Smurray} 105116576Smurray 106116576SmurrayEFI_STATUS 107116576Smurrayefi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) 108116576Smurray{ 109116576Smurray EFI_PHYSICAL_ADDRESS mem; 110116576Smurray EFI_LOADED_IMAGE *img; 111116576Smurray EFI_SIMPLE_NETWORK *net; 112116576Smurray EFI_STATUS status; 113116576Smurray struct ia64_pal_result res; 114116576Smurray char buf[32]; 115116576Smurray int i; 116116576Smurray 117116576Smurray efi_init(image_handle, system_table); 118116576Smurray 119116576Smurray /* 120116576Smurray * Initialise the heap as early as possible. Once this is done, 121116576Smurray * alloc() is usable. The stack is buried inside us, so this is 122116576Smurray * safe. 123116576Smurray */ 124116576Smurray BS->AllocatePages(AllocateAnyPages, EfiLoaderData, 125116576Smurray 512*1024/4096, &mem); 126116576Smurray setheap((void *)mem, (void *)(mem + 512*1024)); 127116576Smurray 128116576Smurray /* 129116576Smurray * XXX Chicken-and-egg problem; we want to have console output 130116576Smurray * early, but some console attributes may depend on reading from 131116576Smurray * eg. the boot device, which we can't do yet. We can use 132116576Smurray * printf() etc. once this is done. 133116576Smurray */ 134116576Smurray cons_probe(); 135116576Smurray 136116576Smurray /* 137116576Smurray * Initialise the block cache 138116576Smurray */ 139116576Smurray bcache_init(32, 512); /* 16k XXX tune this */ 140 141 find_pal_proc(); 142 143 /* 144 * March through the device switch probing for things. 145 */ 146 for (i = 0; devsw[i] != NULL; i++) 147 if (devsw[i]->dv_init != NULL) 148 (devsw[i]->dv_init)(); 149 150 efinet_init_driver(); 151 152 printf("\n"); 153 printf("%s, Revision %s\n", bootprog_name, bootprog_rev); 154 printf("(%s, %s)\n", bootprog_maker, bootprog_date); 155#if 0 156 printf("Memory: %ld k\n", memsize() / 1024); 157#endif 158 159 160 /* 161 * XXX quick and dirty check to see if we're loaded from the 162 * network. If so, we set the default device to 'net'. In all 163 * other cases we set the default device to 'disk'. We presume 164 * fixed positions in devsw for both net and disk. 165 */ 166 BS->HandleProtocol(image_handle, &imgid, (VOID**)&img); 167 168 status = BS->HandleProtocol(img->DeviceHandle, &netid, (VOID**)&net); 169 if (status == EFI_SUCCESS && net != NULL) { 170 currdev.d_dev = devsw[1]; /* XXX net */ 171 currdev.d_kind.netif.unit = 0; 172 } else { 173 currdev.d_dev = devsw[0]; /* XXX disk */ 174 currdev.d_kind.efidisk.unit = 0; 175 /* XXX should be able to detect this, default to autoprobe */ 176 currdev.d_kind.efidisk.slice = -1; 177 /* default to 'a' */ 178 currdev.d_kind.efidisk.partition = 0; 179 } 180 181 currdev.d_type = currdev.d_dev->dv_type; 182 183 /* 184 * Disable the watchdog timer. By default the boot manager sets 185 * the timer to 5 minutes before invoking a boot option. If we 186 * want to return to the boot manager, we have to disable the 187 * watchdog timer and since we're an interactive program, we don't 188 * want to wait until the user types "quit". The timer may have 189 * fired by then. We don't care if this fails. It does not prevent 190 * normal functioning in any way... 191 */ 192 BS->SetWatchdogTimer(0, 0, 0, NULL); 193 194 env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev), 195 efi_setcurrdev, env_nounset); 196 env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset, 197 env_nounset); 198 199 setenv("LINES", "24", 1); /* optional */ 200 201 archsw.arch_autoload = efi_autoload; 202 archsw.arch_getdev = efi_getdev; 203 archsw.arch_copyin = efi_copyin; 204 archsw.arch_copyout = efi_copyout; 205 archsw.arch_readin = efi_readin; 206 207 interact(); /* doesn't return */ 208 209 return (EFI_SUCCESS); /* keep compiler happy */ 210} 211 212COMMAND_SET(quit, "quit", "exit the loader", command_quit); 213 214static int 215command_quit(int argc, char *argv[]) 216{ 217 exit(0); 218 return (CMD_OK); 219} 220 221COMMAND_SET(memmap, "memmap", "print memory map", command_memmap); 222 223static int 224command_memmap(int argc, char *argv[]) 225{ 226 UINTN sz; 227 EFI_MEMORY_DESCRIPTOR *map, *p; 228 UINTN key, dsz; 229 UINT32 dver; 230 EFI_STATUS status; 231 int i, ndesc; 232 static char *types[] = { 233 "Reserved", 234 "LoaderCode", 235 "LoaderData", 236 "BootServicesCode", 237 "BootServicesData", 238 "RuntimeServicesCode", 239 "RuntimeServicesData", 240 "ConventionalMemory", 241 "UnusableMemory", 242 "ACPIReclaimMemory", 243 "ACPIMemoryNVS", 244 "MemoryMappedIO", 245 "MemoryMappedIOPortSpace", 246 "PalCode" 247 }; 248 249 sz = 0; 250 status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver); 251 if (status != EFI_BUFFER_TOO_SMALL) { 252 printf("Can't determine memory map size\n"); 253 return CMD_ERROR; 254 } 255 map = malloc(sz); 256 status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver); 257 if (EFI_ERROR(status)) { 258 printf("Can't read memory map\n"); 259 return CMD_ERROR; 260 } 261 262 ndesc = sz / dsz; 263 printf("%23s %12s %12s %8s %4s\n", 264 "Type", "Physical", "Virtual", "#Pages", "Attr"); 265 266 for (i = 0, p = map; i < ndesc; 267 i++, p = NextMemoryDescriptor(p, dsz)) { 268 printf("%23s %012lx %012lx %08lx ", 269 types[p->Type], 270 p->PhysicalStart, 271 p->VirtualStart, 272 p->NumberOfPages); 273 if (p->Attribute & EFI_MEMORY_UC) 274 printf("UC "); 275 if (p->Attribute & EFI_MEMORY_WC) 276 printf("WC "); 277 if (p->Attribute & EFI_MEMORY_WT) 278 printf("WT "); 279 if (p->Attribute & EFI_MEMORY_WB) 280 printf("WB "); 281 if (p->Attribute & EFI_MEMORY_UCE) 282 printf("UCE "); 283 if (p->Attribute & EFI_MEMORY_WP) 284 printf("WP "); 285 if (p->Attribute & EFI_MEMORY_RP) 286 printf("RP "); 287 if (p->Attribute & EFI_MEMORY_XP) 288 printf("XP "); 289 if (p->Attribute & EFI_MEMORY_RUNTIME) 290 printf("RUNTIME"); 291 printf("\n"); 292 } 293 294 return CMD_OK; 295} 296 297COMMAND_SET(configuration, "configuration", 298 "print configuration tables", command_configuration); 299 300static const char * 301guid_to_string(EFI_GUID *guid) 302{ 303 static char buf[40]; 304 305 sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 306 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], 307 guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4], 308 guid->Data4[5], guid->Data4[6], guid->Data4[7]); 309 return (buf); 310} 311 312static int 313command_configuration(int argc, char *argv[]) 314{ 315 int i; 316 317 printf("NumberOfTableEntries=%ld\n", ST->NumberOfTableEntries); 318 for (i = 0; i < ST->NumberOfTableEntries; i++) { 319 EFI_GUID *guid; 320 321 printf(" "); 322 guid = &ST->ConfigurationTable[i].VendorGuid; 323 if (!memcmp(guid, &mps, sizeof(EFI_GUID))) 324 printf("MPS Table"); 325 else if (!memcmp(guid, &acpi, sizeof(EFI_GUID))) 326 printf("ACPI Table"); 327 else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID))) 328 printf("ACPI 2.0 Table"); 329 else if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) 330 printf("SMBIOS Table"); 331 else if (!memcmp(guid, &sal, sizeof(EFI_GUID))) 332 printf("SAL System Table"); 333 else if (!memcmp(guid, &hcdp, sizeof(EFI_GUID))) 334 printf("DIG64 HCDP Table"); 335 else 336 printf("Unknown Table (%s)", guid_to_string(guid)); 337 printf(" at %p\n", ST->ConfigurationTable[i].VendorTable); 338 } 339 340 return CMD_OK; 341} 342 343COMMAND_SET(sal, "sal", "print SAL System Table", command_sal); 344 345static int 346command_sal(int argc, char *argv[]) 347{ 348 int i; 349 struct sal_system_table *saltab = 0; 350 static int sizes[6] = { 351 48, 32, 16, 32, 16, 16 352 }; 353 u_int8_t *p; 354 355 for (i = 0; i < ST->NumberOfTableEntries; i++) { 356 if (!memcmp(&ST->ConfigurationTable[i].VendorGuid, 357 &sal, sizeof(EFI_GUID))) 358 saltab = ST->ConfigurationTable[i].VendorTable; 359 } 360 361 if (!saltab) { 362 printf("Can't find SAL System Table\n"); 363 return CMD_ERROR; 364 } 365 366 if (memcmp(saltab->sal_signature, "SST_", 4)) { 367 printf("Bad signature for SAL System Table\n"); 368 return CMD_ERROR; 369 } 370 371 printf("SAL Revision %x.%02x\n", 372 saltab->sal_rev[1], 373 saltab->sal_rev[0]); 374 printf("SAL A Version %x.%02x\n", 375 saltab->sal_a_version[1], 376 saltab->sal_a_version[0]); 377 printf("SAL B Version %x.%02x\n", 378 saltab->sal_b_version[1], 379 saltab->sal_b_version[0]); 380 381 p = (u_int8_t *) (saltab + 1); 382 for (i = 0; i < saltab->sal_entry_count; i++) { 383 printf(" Desc %d", *p); 384 if (*p == 0) { 385 struct sal_entrypoint_descriptor *dp; 386 dp = (struct sal_entrypoint_descriptor *) p; 387 printf("\n"); 388 printf(" PAL Proc at 0x%lx\n", 389 dp->sale_pal_proc); 390 printf(" SAL Proc at 0x%lx\n", 391 dp->sale_sal_proc); 392 printf(" SAL GP at 0x%lx\n", 393 dp->sale_sal_gp); 394 } else if (*p == 1) { 395 struct sal_memory_descriptor *dp; 396 dp = (struct sal_memory_descriptor *) p; 397 printf(" Type %d.%d, ", 398 dp->sale_memory_type[0], 399 dp->sale_memory_type[1]); 400 printf("Address 0x%lx, ", 401 dp->sale_physical_address); 402 printf("Length 0x%x\n", 403 dp->sale_length); 404 } else if (*p == 5) { 405 struct sal_ap_wakeup_descriptor *dp; 406 dp = (struct sal_ap_wakeup_descriptor *) p; 407 printf("\n"); 408 printf(" Mechanism %d\n", dp->sale_mechanism); 409 printf(" Vector 0x%lx\n", dp->sale_vector); 410 } else 411 printf("\n"); 412 413 p += sizes[*p]; 414 } 415 416 return CMD_OK; 417} 418 419int 420print_trs(int type) 421{ 422 struct ia64_pal_result res; 423 int i, maxtr; 424 struct { 425 struct ia64_pte pte; 426 struct ia64_itir itir; 427 struct ia64_ifa ifa; 428 struct ia64_rr rr; 429 } buf; 430 static const char* psnames[] = { 431 "1B", "2B", "4B", "8B", 432 "16B", "32B", "64B", "128B", 433 "256B", "512B", "1K", "2K", 434 "4K", "8K", "16K", "32K", 435 "64K", "128K", "256K", "512K", 436 "1M", "2M", "4M", "8M", 437 "16M", "32M", "64M", "128M", 438 "256M", "512M", "1G", "2G" 439 }; 440 static const char* manames[] = { 441 "WB", "bad", "bad", "bad", 442 "UC", "UCE", "WC", "NaT", 443 444 }; 445 446 res = ia64_call_pal_static(PAL_VM_SUMMARY, 0, 0, 0); 447 if (res.pal_status != 0) { 448 printf("Can't get VM summary\n"); 449 return CMD_ERROR; 450 } 451 452 if (type == 0) 453 maxtr = (res.pal_result[0] >> 40) & 0xff; 454 else 455 maxtr = (res.pal_result[0] >> 32) & 0xff; 456 457 printf("%d translation registers\n", maxtr); 458 459 pager_open(); 460 pager_output("TR# RID Virtual Page Physical Page PgSz ED AR PL D A MA P KEY\n"); 461 for (i = 0; i <= maxtr; i++) { 462 char lbuf[128]; 463 464 bzero(&buf, sizeof(buf)); 465 res = ia64_call_pal_stacked(PAL_VM_TR_READ, i, type, 466 (u_int64_t) &buf); 467 if (res.pal_status != 0) 468 break; 469 470 /* Only display valid translations */ 471 if ((buf.ifa.ifa_ig & 1) == 0) 472 continue; 473 474 if (!(res.pal_result[0] & 1)) 475 buf.pte.pte_ar = 0; 476 if (!(res.pal_result[0] & 2)) 477 buf.pte.pte_pl = 0; 478 if (!(res.pal_result[0] & 4)) 479 buf.pte.pte_d = 0; 480 if (!(res.pal_result[0] & 8)) 481 buf.pte.pte_ma = 0; 482 sprintf(lbuf, 483 "%03d %06x %013lx %013lx %4s %d %d %d %d %d %-3s %d %06x\n", 484 i, 485 buf.rr.rr_rid, 486 buf.ifa.ifa_vpn, 487 buf.pte.pte_ppn, 488 psnames[buf.itir.itir_ps], 489 buf.pte.pte_ed, 490 buf.pte.pte_ar, 491 buf.pte.pte_pl, 492 buf.pte.pte_d, 493 buf.pte.pte_a, 494 manames[buf.pte.pte_ma], 495 buf.pte.pte_p, 496 buf.itir.itir_key); 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 508COMMAND_SET(itr, "itr", "print instruction TRs", command_itr); 509 510static int 511command_itr(int argc, char *argv[]) 512{ 513 return print_trs(0); 514} 515 516COMMAND_SET(dtr, "dtr", "print data TRs", command_dtr); 517 518static int 519command_dtr(int argc, char *argv[]) 520{ 521 return print_trs(1); 522} 523 524