main.c revision 93411
1290001Sglebius/*- 2290001Sglebius * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3290001Sglebius * Copyright (c) 1998,2000 Doug Rabson <dfr@freebsd.org> 4290001Sglebius * All rights reserved. 5290001Sglebius * 6290001Sglebius * Redistribution and use in source and binary forms, with or without 7290001Sglebius * modification, are permitted provided that the following conditions 8290001Sglebius * are met: 9290001Sglebius * 1. Redistributions of source code must retain the above copyright 10290001Sglebius * notice, this list of conditions and the following disclaimer. 11290001Sglebius * 2. Redistributions in binary form must reproduce the above copyright 12290001Sglebius * notice, this list of conditions and the following disclaimer in the 13290001Sglebius * documentation and/or other materials provided with the distribution. 14290001Sglebius * 15290001Sglebius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16290001Sglebius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17290001Sglebius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18290001Sglebius * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19290001Sglebius * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20290001Sglebius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21290001Sglebius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22290001Sglebius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23290001Sglebius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24290001Sglebius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25290001Sglebius * SUCH DAMAGE. 26290001Sglebius */ 27290001Sglebius 28290001Sglebius#ifndef lint 29290001Sglebiusstatic const char rcsid[] = 30290001Sglebius "$FreeBSD: head/sys/boot/ia64/efi/main.c 93411 2002-03-30 07:32:08Z marcel $"; 31290001Sglebius#endif /* not lint */ 32290001Sglebius 33290001Sglebius#include <stand.h> 34290001Sglebius#include <string.h> 35290001Sglebius#include <setjmp.h> 36290001Sglebius#include <machine/sal.h> 37290001Sglebius#include <machine/pal.h> 38290001Sglebius#include <machine/pte.h> 39290001Sglebius 40290001Sglebius#include <efi.h> 41290001Sglebius#include <efilib.h> 42290001Sglebius 43290001Sglebius#include "bootstrap.h" 44290001Sglebius#include "efiboot.h" 45290001Sglebius 46290001Sglebiusextern char bootprog_name[]; 47290001Sglebiusextern char bootprog_rev[]; 48290001Sglebiusextern char bootprog_date[]; 49290001Sglebiusextern char bootprog_maker[]; 50290001Sglebius 51290001Sglebiusstruct efi_devdesc currdev; /* our current device */ 52290001Sglebiusstruct arch_switch archsw; /* MI/MD interface boundary */ 53290001Sglebius 54290001Sglebiusextern u_int64_t ia64_pal_entry; 55290001Sglebius 56290001Sglebiusstatic void 57290001Sglebiusfind_pal_proc(void) 58290001Sglebius{ 59290001Sglebius int i; 60290001Sglebius struct sal_system_table *saltab = 0; 61290001Sglebius static int sizes[6] = { 62290001Sglebius 48, 32, 16, 32, 16, 16 63290001Sglebius }; 64290001Sglebius u_int8_t *p; 65290001Sglebius 66290001Sglebius for (i = 0; i < ST->NumberOfTableEntries; i++) { 67290001Sglebius static EFI_GUID sal = SAL_SYSTEM_TABLE_GUID; 68290001Sglebius if (!memcmp(&ST->ConfigurationTable[i].VendorGuid, 69290001Sglebius &sal, sizeof(EFI_GUID))) 70290001Sglebius saltab = ST->ConfigurationTable[i].VendorTable; 71290001Sglebius } 72290001Sglebius 73290001Sglebius if (!saltab) { 74290001Sglebius printf("Can't find SAL System Table\n"); 75290001Sglebius return; 76290001Sglebius } 77290001Sglebius 78290001Sglebius if (memcmp(saltab->sal_signature, "SST_", 4)) { 79290001Sglebius printf("Bad signature for SAL System Table\n"); 80290001Sglebius return; 81290001Sglebius } 82290001Sglebius 83290001Sglebius p = (u_int8_t *) (saltab + 1); 84290001Sglebius for (i = 0; i < saltab->sal_entry_count; i++) { 85290001Sglebius if (*p == 0) { 86290001Sglebius struct sal_entrypoint_descriptor *dp; 87290001Sglebius dp = (struct sal_entrypoint_descriptor *) p; 88290001Sglebius ia64_pal_entry = dp->sale_pal_proc; 89290001Sglebius return; 90290001Sglebius } 91290001Sglebius p += sizes[*p]; 92290001Sglebius } 93290001Sglebius 94290001Sglebius printf("Can't find PAL proc\n"); 95290001Sglebius return; 96290001Sglebius} 97290001Sglebius 98290001SglebiusEFI_STATUS 99290001Sglebiusefi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) 100290001Sglebius{ 101290001Sglebius static EFI_GUID imgid = LOADED_IMAGE_PROTOCOL; 102290001Sglebius static EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL; 103290001Sglebius EFI_PHYSICAL_ADDRESS mem; 104290001Sglebius EFI_LOADED_IMAGE *img; 105290001Sglebius EFI_SIMPLE_NETWORK *net; 106290001Sglebius EFI_STATUS status; 107290001Sglebius struct ia64_pal_result res; 108290001Sglebius char buf[32]; 109290001Sglebius int i; 110290001Sglebius 111290001Sglebius efi_init(image_handle, system_table); 112290001Sglebius 113290001Sglebius /* 114290001Sglebius * Initialise the heap as early as possible. Once this is done, 115290001Sglebius * alloc() is usable. The stack is buried inside us, so this is 116290001Sglebius * safe. 117290001Sglebius */ 118290001Sglebius BS->AllocatePages(AllocateAnyPages, EfiLoaderData, 119290001Sglebius 512*1024/4096, &mem); 120290001Sglebius setheap((void *)mem, (void *)(mem + 512*1024)); 121290001Sglebius 122290001Sglebius /* 123290001Sglebius * XXX Chicken-and-egg problem; we want to have console output 124290001Sglebius * early, but some console attributes may depend on reading from 125290001Sglebius * eg. the boot device, which we can't do yet. We can use 126290001Sglebius * printf() etc. once this is done. 127290001Sglebius */ 128290001Sglebius cons_probe(); 129290001Sglebius 130290001Sglebius /* 131290001Sglebius * Initialise the block cache 132290001Sglebius */ 133290001Sglebius bcache_init(32, 512); /* 16k XXX tune this */ 134290001Sglebius 135290001Sglebius find_pal_proc(); 136290001Sglebius 137290001Sglebius /* 138290001Sglebius * March through the device switch probing for things. 139290001Sglebius */ 140290001Sglebius for (i = 0; devsw[i] != NULL; i++) 141290001Sglebius if (devsw[i]->dv_init != NULL) 142290001Sglebius (devsw[i]->dv_init)(); 143290001Sglebius 144290001Sglebius efinet_init_driver(); 145290001Sglebius 146290001Sglebius printf("\n"); 147290001Sglebius printf("%s, Revision %s\n", bootprog_name, bootprog_rev); 148290001Sglebius printf("(%s, %s)\n", bootprog_maker, bootprog_date); 149290001Sglebius#if 0 150290001Sglebius printf("Memory: %ld k\n", memsize() / 1024); 151290001Sglebius#endif 152290001Sglebius 153290001Sglebius 154290001Sglebius /* 155290001Sglebius * XXX quick and dirty check to see if we're loaded from the 156290001Sglebius * network. If so, we set the default device to 'net'. In all 157290001Sglebius * other cases we set the default device to 'disk'. We presume 158290001Sglebius * fixed positions in devsw for both net and disk. 159290001Sglebius */ 160290001Sglebius BS->HandleProtocol(image_handle, &imgid, (VOID**)&img); 161290001Sglebius 162290001Sglebius status = BS->HandleProtocol(img->DeviceHandle, &netid, (VOID**)&net); 163290001Sglebius if (status == EFI_SUCCESS && net != NULL) { 164290001Sglebius currdev.d_dev = devsw[1]; /* XXX net */ 165290001Sglebius currdev.d_kind.netif.unit = 0; 166290001Sglebius } else { 167290001Sglebius currdev.d_dev = devsw[0]; /* XXX disk */ 168290001Sglebius currdev.d_kind.efidisk.unit = 0; 169290001Sglebius /* XXX should be able to detect this, default to autoprobe */ 170290001Sglebius currdev.d_kind.efidisk.slice = -1; 171290001Sglebius /* default to 'a' */ 172290001Sglebius currdev.d_kind.efidisk.partition = 0; 173290001Sglebius } 174290001Sglebius 175290001Sglebius currdev.d_type = currdev.d_dev->dv_type; 176290001Sglebius 177290001Sglebius#if 0 178290001Sglebius /* Create arc-specific variables */ 179290001Sglebius bootfile = GetEnvironmentVariable(ARCENV_BOOTFILE); 180290001Sglebius if (bootfile) 181290001Sglebius setenv("bootfile", bootfile, 1); 182290001Sglebius#endif 183290001Sglebius 184290001Sglebius env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev), 185290001Sglebius efi_setcurrdev, env_nounset); 186290001Sglebius env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset, 187290001Sglebius env_nounset); 188290001Sglebius 189290001Sglebius setenv("LINES", "24", 1); /* optional */ 190290001Sglebius 191290001Sglebius archsw.arch_autoload = efi_autoload; 192290001Sglebius archsw.arch_getdev = efi_getdev; 193290001Sglebius archsw.arch_copyin = efi_copyin; 194290001Sglebius archsw.arch_copyout = efi_copyout; 195290001Sglebius archsw.arch_readin = efi_readin; 196290001Sglebius 197290001Sglebius interact(); /* doesn't return */ 198290001Sglebius 199290001Sglebius return (EFI_SUCCESS); /* keep compiler happy */ 200290001Sglebius} 201290001Sglebius 202290001SglebiusCOMMAND_SET(quit, "quit", "exit the loader", command_quit); 203290001Sglebius 204290001Sglebiusstatic int 205290001Sglebiuscommand_quit(int argc, char *argv[]) 206290001Sglebius{ 207290001Sglebius exit(0); 208290001Sglebius return (CMD_OK); 209290001Sglebius} 210290001Sglebius 211290001SglebiusCOMMAND_SET(memmap, "memmap", "print memory map", command_memmap); 212290001Sglebius 213290001Sglebiusstatic int 214290001Sglebiuscommand_memmap(int argc, char *argv[]) 215290001Sglebius{ 216290001Sglebius UINTN sz; 217290001Sglebius EFI_MEMORY_DESCRIPTOR *map, *p; 218290001Sglebius UINTN key, dsz; 219290001Sglebius UINT32 dver; 220290001Sglebius EFI_STATUS status; 221290001Sglebius int i, ndesc; 222290001Sglebius static char *types[] = { 223290001Sglebius "Reserved", 224290001Sglebius "LoaderCode", 225290001Sglebius "LoaderData", 226290001Sglebius "BootServicesCode", 227290001Sglebius "BootServicesData", 228290001Sglebius "RuntimeServicesCode", 229290001Sglebius "RuntimeServicesData", 230290001Sglebius "ConventionalMemory", 231290001Sglebius "UnusableMemory", 232290001Sglebius "ACPIReclaimMemory", 233290001Sglebius "ACPIMemoryNVS", 234290001Sglebius "MemoryMappedIO", 235290001Sglebius "MemoryMappedIOPortSpace", 236290001Sglebius "PalCode" 237290001Sglebius }; 238290001Sglebius 239290001Sglebius sz = 0; 240290001Sglebius status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver); 241290001Sglebius if (status != EFI_BUFFER_TOO_SMALL) { 242290001Sglebius printf("Can't determine memory map size\n"); 243290001Sglebius return CMD_ERROR; 244290001Sglebius } 245290001Sglebius map = malloc(sz); 246290001Sglebius status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver); 247290001Sglebius if (EFI_ERROR(status)) { 248290001Sglebius printf("Can't read memory map\n"); 249290001Sglebius return CMD_ERROR; 250290001Sglebius } 251290001Sglebius 252290001Sglebius ndesc = sz / dsz; 253290001Sglebius printf("%23s %12s %12s %8s %4s\n", 254290001Sglebius "Type", "Physical", "Virtual", "#Pages", "Attr"); 255290001Sglebius 256290001Sglebius for (i = 0, p = map; i < ndesc; 257290001Sglebius i++, p = NextMemoryDescriptor(p, dsz)) { 258290001Sglebius printf("%23s %012lx %012lx %08lx ", 259290001Sglebius types[p->Type], 260290001Sglebius p->PhysicalStart, 261290001Sglebius p->VirtualStart, 262290001Sglebius p->NumberOfPages); 263290001Sglebius if (p->Attribute & EFI_MEMORY_UC) 264290001Sglebius printf("UC "); 265290001Sglebius if (p->Attribute & EFI_MEMORY_WC) 266290001Sglebius printf("WC "); 267290001Sglebius if (p->Attribute & EFI_MEMORY_WT) 268290001Sglebius printf("WT "); 269290001Sglebius if (p->Attribute & EFI_MEMORY_WB) 270290001Sglebius printf("WB "); 271290001Sglebius if (p->Attribute & EFI_MEMORY_UCE) 272290001Sglebius printf("UCE "); 273290001Sglebius if (p->Attribute & EFI_MEMORY_WP) 274290001Sglebius printf("WP "); 275290001Sglebius if (p->Attribute & EFI_MEMORY_RP) 276290001Sglebius printf("RP "); 277290001Sglebius if (p->Attribute & EFI_MEMORY_XP) 278290001Sglebius printf("XP "); 279290001Sglebius if (p->Attribute & EFI_MEMORY_RUNTIME) 280290001Sglebius printf("RUNTIME"); 281290001Sglebius printf("\n"); 282290001Sglebius } 283290001Sglebius 284290001Sglebius return CMD_OK; 285290001Sglebius} 286290001Sglebius 287290001SglebiusCOMMAND_SET(configuration, "configuration", 288290001Sglebius "print configuration tables", command_configuration); 289290001Sglebius 290290001Sglebiusstatic int 291290001Sglebiuscommand_configuration(int argc, char *argv[]) 292290001Sglebius{ 293290001Sglebius int i; 294290001Sglebius 295290001Sglebius printf("NumberOfTableEntries=%d\n", ST->NumberOfTableEntries); 296290001Sglebius for (i = 0; i < ST->NumberOfTableEntries; i++) { 297290001Sglebius static EFI_GUID mps = MPS_TABLE_GUID; 298290001Sglebius static EFI_GUID acpi = ACPI_TABLE_GUID; 299290001Sglebius static EFI_GUID acpi20 = ACPI_20_TABLE_GUID; 300290001Sglebius static EFI_GUID smbios = SMBIOS_TABLE_GUID; 301290001Sglebius static EFI_GUID sal = SAL_SYSTEM_TABLE_GUID; 302 303 printf(" "); 304 if (!memcmp(&ST->ConfigurationTable[i].VendorGuid, 305 &mps, sizeof(EFI_GUID))) 306 printf("MPS Table"); 307 else if (!memcmp(&ST->ConfigurationTable[i].VendorGuid, 308 &acpi, sizeof(EFI_GUID))) 309 printf("ACPI Table"); 310 else if (!memcmp(&ST->ConfigurationTable[i].VendorGuid, 311 &acpi20, sizeof(EFI_GUID))) 312 printf("ACPI 2.0 Table"); 313 else if (!memcmp(&ST->ConfigurationTable[i].VendorGuid, 314 &smbios, sizeof(EFI_GUID))) 315 printf("SMBIOS Table"); 316 else if (!memcmp(&ST->ConfigurationTable[i].VendorGuid, 317 &sal, sizeof(EFI_GUID))) 318 printf("SAL System Table"); 319 else 320 printf("Unknown Table"); 321 printf(" at %p\n", ST->ConfigurationTable[i].VendorTable); 322 } 323 324 return CMD_OK; 325} 326 327COMMAND_SET(sal, "sal", "print SAL System Table", command_sal); 328 329static int 330command_sal(int argc, char *argv[]) 331{ 332 int i; 333 struct sal_system_table *saltab = 0; 334 static int sizes[6] = { 335 48, 32, 16, 32, 16, 16 336 }; 337 u_int8_t *p; 338 339 for (i = 0; i < ST->NumberOfTableEntries; i++) { 340 static EFI_GUID sal = SAL_SYSTEM_TABLE_GUID; 341 if (!memcmp(&ST->ConfigurationTable[i].VendorGuid, 342 &sal, sizeof(EFI_GUID))) 343 saltab = ST->ConfigurationTable[i].VendorTable; 344 } 345 346 if (!saltab) { 347 printf("Can't find SAL System Table\n"); 348 return CMD_ERROR; 349 } 350 351 if (memcmp(saltab->sal_signature, "SST_", 4)) { 352 printf("Bad signature for SAL System Table\n"); 353 return CMD_ERROR; 354 } 355 356 printf("SAL Revision %x.%02x\n", 357 saltab->sal_rev[1], 358 saltab->sal_rev[0]); 359 printf("SAL A Version %x.%02x\n", 360 saltab->sal_a_version[1], 361 saltab->sal_a_version[0]); 362 printf("SAL B Version %x.%02x\n", 363 saltab->sal_b_version[1], 364 saltab->sal_b_version[0]); 365 366 p = (u_int8_t *) (saltab + 1); 367 for (i = 0; i < saltab->sal_entry_count; i++) { 368 printf(" Desc %d", *p); 369 if (*p == 0) { 370 struct sal_entrypoint_descriptor *dp; 371 dp = (struct sal_entrypoint_descriptor *) p; 372 printf("\n"); 373 printf(" PAL Proc at 0x%lx\n", 374 dp->sale_pal_proc); 375 printf(" SAL Proc at 0x%lx\n", 376 dp->sale_sal_proc); 377 printf(" SAL GP at 0x%lx\n", 378 dp->sale_sal_gp); 379 } else if (*p == 1) { 380 struct sal_memory_descriptor *dp; 381 dp = (struct sal_memory_descriptor *) p; 382 printf(" Type %d.%d, ", 383 dp->sale_memory_type[0], 384 dp->sale_memory_type[1]); 385 printf("Address 0x%lx, ", 386 dp->sale_physical_address); 387 printf("Length 0x%x\n", 388 dp->sale_length); 389 } else { 390 printf("\n"); 391 } 392 p += sizes[*p]; 393 } 394 395 return CMD_OK; 396} 397 398int 399print_trs(int type) 400{ 401 struct ia64_pal_result res; 402 int i, maxtr; 403 struct { 404 struct ia64_pte pte; 405 struct ia64_itir itir; 406 struct ia64_ifa ifa; 407 struct ia64_rr rr; 408 } buf; 409 static const char* psnames[] = { 410 "1B", "2B", "4B", "8B", 411 "16B", "32B", "64B", "128B", 412 "256B", "512B", "1K", "2K", 413 "4K", "8K", "16K", "32K", 414 "64K", "128K", "256K", "512K", 415 "1M", "2M", "4M", "8M", 416 "16M", "32M", "64M", "128M", 417 "256M", "512M", "1G", "2G" 418 }; 419 static const char* manames[] = { 420 "WB", "bad", "bad", "bad", 421 "UC", "UCE", "WC", "NaT", 422 423 }; 424 425 res = ia64_call_pal_static(PAL_VM_SUMMARY, 0, 0, 0); 426 if (res.pal_status != 0) { 427 printf("Can't get VM summary\n"); 428 return CMD_ERROR; 429 } 430 431 if (type == 0) 432 maxtr = (res.pal_result[0] >> 40) & 0xff; 433 else 434 maxtr = (res.pal_result[0] >> 32) & 0xff; 435 436 pager_open(); 437 pager_output("V RID Virtual Page Physical Page PgSz ED AR PL D A MA P KEY\n"); 438 for (i = 0; i <= maxtr; i++) { 439 char lbuf[128]; 440 441 bzero(&buf, sizeof(buf)); 442 res = ia64_call_pal_stacked(PAL_VM_TR_READ, i, type, 443 (u_int64_t) &buf); 444 if (!(res.pal_result[0] & 1)) 445 buf.pte.pte_ar = 0; 446 if (!(res.pal_result[0] & 2)) 447 buf.pte.pte_pl = 0; 448 if (!(res.pal_result[0] & 4)) 449 buf.pte.pte_d = 0; 450 if (!(res.pal_result[0] & 8)) 451 buf.pte.pte_ma = 0; 452 sprintf(lbuf, 453 "%d %06x %013x %013x %4s %d %d %d %d %d %-3s %d %06x\n", 454 buf.ifa.ifa_ig & 1, 455 buf.rr.rr_rid, 456 buf.ifa.ifa_vpn, 457 buf.pte.pte_ppn, 458 psnames[buf.itir.itir_ps], 459 buf.pte.pte_ed, 460 buf.pte.pte_ar, 461 buf.pte.pte_pl, 462 buf.pte.pte_d, 463 buf.pte.pte_a, 464 manames[buf.pte.pte_ma], 465 buf.pte.pte_p, 466 buf.itir.itir_key); 467 pager_output(lbuf); 468 } 469 pager_close(); 470 471 return CMD_OK; 472} 473 474COMMAND_SET(itr, "itr", "print instruction TRs", command_itr); 475 476static int 477command_itr(int argc, char *argv[]) 478{ 479 return print_trs(0); 480} 481 482COMMAND_SET(dtr, "dtr", "print data TRs", command_dtr); 483 484static int 485command_dtr(int argc, char *argv[]) 486{ 487 return print_trs(1); 488} 489 490