|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 2006 JLA ! 4: ! 5: Module Name: ! 6: ! 7: jlaefi.c ! 8: ! 9: Abstract: ! 10: ! 11: EFI helper routines ! 12: ! 13: Revision History ! 14: ! 15: --*/ ! 16: ! 17: #include "efi.h" ! 18: #include "efilib.h" ! 19: #include "../lib/jlaefi.h" ! 20: ! 21: EFI_HANDLE imageHandle; ! 22: EFI_LOADED_IMAGE* pLoadedImage; ! 23: struct _EFI_CONSOLE_CONTROL_PROTOCOL* pConsoleControl; ! 24: SIMPLE_INPUT_INTERFACE* pKeyboard; ! 25: EFI_UGA_DRAW_PROTOCOL* pUgaDraw = 0; ! 26: EFI_DECOMPRESS_PROTOCOL* pDecompress; ! 27: ! 28: UINTN argc; ! 29: CHAR16** argv; ! 30: EFI_STATUS status; ! 31: ! 32: #define SHELL_INTERFACE_PROTOCOL \ ! 33: { 0x47c7b223, 0xc42a, 0x11d2, 0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } ! 34: ! 35: EFI_GUID ShellInterfaceProtocol = SHELL_INTERFACE_PROTOCOL; ! 36: ! 37: typedef struct _EFI_SHELL_INTERFACE { ! 38: // Handle back to original image handle & image info ! 39: EFI_HANDLE ImageHandle; ! 40: EFI_LOADED_IMAGE *Info; ! 41: ! 42: // Parsed arg list ! 43: CHAR16 **Argv; ! 44: UINTN Argc; ! 45: ! 46: // Storage for file redirection args after parsing ! 47: CHAR16 **RedirArgv; ! 48: UINTN RedirArgc; ! 49: ! 50: // A file style handle for console io ! 51: EFI_FILE_HANDLE StdIn; ! 52: EFI_FILE_HANDLE StdOut; ! 53: EFI_FILE_HANDLE StdErr; ! 54: ! 55: } EFI_SHELL_INTERFACE; ! 56: ! 57: EFI_GUID ConsoleControlProtocol = { 0xF42F7782, 0x012E, 0x4C12, 0x99, 0x56, 0x49, 0xf9, 0x43, 0x04, 0xf7, 0x21 }; ! 58: ! 59: typedef enum { ! 60: EfiConsoleControlScreenText, ! 61: EfiConsoleControlScreenGraphics, ! 62: EfiConsoleControlScreenMax, ! 63: } EFI_CONSOLE_CONTROL_SCREEN_MODE; ! 64: ! 65: typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL { ! 66: void (*GetMode)(struct _EFI_CONSOLE_CONTROL_PROTOCOL* pThis, EFI_CONSOLE_CONTROL_SCREEN_MODE* currentMode, UINT32 n0, UINT32 n1); ! 67: void (*SetMode)(struct _EFI_CONSOLE_CONTROL_PROTOCOL* pThis, EFI_CONSOLE_CONTROL_SCREEN_MODE currentMode); ! 68: } EFI_CONSOLE_CONTROL_PROTOCOL; ! 69: ! 70: void InitJLAEFI(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { ! 71: // ! 72: // Initialize the Library. ! 73: // ! 74: InitializeLib (ImageHandle, SystemTable); ! 75: pKeyboard = SystemTable->ConIn; ! 76: imageHandle = ImageHandle; ! 77: ! 78: // Get loaded image interface to implement exit() function ! 79: status = BS->HandleProtocol(imageHandle, &LoadedImageProtocol, &pLoadedImage); ! 80: if (EFI_ERROR(status)) { ! 81: Print(L"Unable to obtain LoadedImageProtocol interface: %r\n", status); ! 82: exit(EFI_SUCCESS); ! 83: } ! 84: ! 85: // Get console control interface to set text mode ! 86: status = LibLocateProtocol(&ConsoleControlProtocol, &pConsoleControl); ! 87: if (EFI_ERROR(status)) { ! 88: Print(L"Unable to obtain ConsoleControl interface: %r\n", status); ! 89: exit(EFI_SUCCESS); ! 90: } ! 91: ! 92: // Get arg list ! 93: { ! 94: EFI_SHELL_INTERFACE* pShell; ! 95: UINT32 handleCount, i; ! 96: EFI_HANDLE* handles; ! 97: ! 98: LibLocateHandle(ByProtocol, &ShellInterfaceProtocol, NULL, &handleCount, &handles); ! 99: for (i = 0; i < handleCount; ++i) { ! 100: BS->HandleProtocol(handles[i], &ShellInterfaceProtocol, &pShell); ! 101: if (pShell->Argc) ! 102: break; ! 103: } ! 104: ! 105: argc = pShell->Argc; ! 106: argv = pShell->Argv; ! 107: } ! 108: ! 109: // Locate UGA draw ! 110: // My iMac 17" reports that two handles implement UgaDraw ! 111: // But only one actually draws on the screen!! ! 112: // Both report the same resolution, both implement TextOut. ! 113: // And worse... Both TextOut->OutputString print to the screen!! (???) ! 114: // So... in order to draw to the screen, which one should I choose? ! 115: // What has worked so far is using the second one returned (HACK!) ! 116: { ! 117: UINTN NoHandles; ! 118: UINTN Index; ! 119: EFI_HANDLE* Handles; ! 120: ! 121: // Get list of UgaDraw implementors ! 122: LibLocateHandle(ByProtocol, &UgaDrawProtocol, NULL, &NoHandles, &Handles); ! 123: ! 124: // Enumerate all but keep only the last one (HACK!) ! 125: for (Index = 0; Index < NoHandles; Index++) ! 126: BS->HandleProtocol(Handles[Index], &UgaDrawProtocol, &pUgaDraw); ! 127: ! 128: // Sanity ! 129: if (!pUgaDraw) ! 130: Print(L"jlaefi: Unable to find UgaDraw interface\n"); ! 131: } ! 132: ! 133: // Locate decompress algorithm ! 134: status = LibLocateProtocol(&DecompressProtocol, &pDecompress); ! 135: if (EFI_ERROR(status)) { ! 136: Print(L"Unable to obtain Decompress interface: %r\n", status); ! 137: exit(EFI_SUCCESS); ! 138: } ! 139: } ! 140: ! 141: void consoleControl(UINTN graphicsMode) { ! 142: if (pConsoleControl) ! 143: pConsoleControl->SetMode(pConsoleControl, graphicsMode ? EfiConsoleControlScreenGraphics : EfiConsoleControlScreenText); ! 144: } ! 145: ! 146: EFI_STATUS exec(EFI_HANDLE device, CHAR16* filename) { ! 147: EFI_DEVICE_PATH* filePath; ! 148: EFI_HANDLE handle; ! 149: ! 150: if (device == NULL) ! 151: device = pLoadedImage ? pLoadedImage->DeviceHandle : NULL; ! 152: ! 153: if (device == NULL) { ! 154: Print(L"exec(%s): Invalid device\n", filename); ! 155: return EFI_INVALID_PARAMETER; ! 156: } ! 157: ! 158: filePath = FileDevicePath(device, filename); ! 159: if (!filePath) { ! 160: Print(L"exec(%s): Unable to create device path\n", filename); ! 161: return EFI_OUT_OF_RESOURCES; ! 162: } ! 163: ! 164: status = BS->LoadImage(FALSE, imageHandle, filePath, NULL, 0, &handle); ! 165: if (EFI_ERROR(status)) { ! 166: Print(L"exec(%s): Unable to load image: %r\n", filename, status); ! 167: return EFI_NOT_FOUND; ! 168: } ! 169: ! 170: status = BS->StartImage(handle, NULL, NULL); ! 171: if (EFI_ERROR(status)) { ! 172: Print(L"exec(%s): Unable to start image: %r\n", filename, status); ! 173: return EFI_NOT_STARTED; ! 174: } ! 175: return EFI_SUCCESS; ! 176: } ! 177: ! 178: void exit(EFI_STATUS status) { ! 179: consoleControl(0); ! 180: BS->Exit(imageHandle, status, 0, NULL); ! 181: } ! 182: ! 183: CHAR16 inputChar(CHAR16* prompt, CHAR16 dflt) { ! 184: CHAR16 buffer[16]; ! 185: ! 186: Print(L"%s [%c] : ", prompt, dflt); ! 187: Input(NULL, buffer, sizeof(buffer)); ! 188: Print(L"\n"); ! 189: if (buffer[0] == 'q') ! 190: exit(EFI_SUCCESS); ! 191: if (!buffer[0]) ! 192: return dflt; ! 193: return buffer[0]; ! 194: } ! 195: ! 196: UINT32 inputHex(CHAR16* prompt, UINT32 dflt) { ! 197: CHAR16 buffer[16]; ! 198: ! 199: Print(L"%s [%04x] : ", prompt, dflt); ! 200: Input(NULL, buffer, sizeof(buffer)); ! 201: Print(L"\n"); ! 202: if (buffer[0] == 'q') ! 203: exit(EFI_SUCCESS); ! 204: if (!buffer[0]) ! 205: return dflt; ! 206: return xtoi(buffer); ! 207: } ! 208: ! 209: UINT32 inputDec(CHAR16* prompt, UINT32 dflt) { ! 210: CHAR16 buffer[16]; ! 211: ! 212: Print(L"%s [%4d] : ", prompt, dflt); ! 213: Input(NULL, buffer, sizeof(buffer)); ! 214: Print(L"\n"); ! 215: if (buffer[0] == 'q') ! 216: exit(EFI_SUCCESS); ! 217: if (!buffer[0]) ! 218: return dflt; ! 219: return Atoi(buffer); ! 220: } ! 221: ! 222: void saveMemory(EFI_FILE* rootDir, UINT32 address, UINT32 length, UINTN copyFirst) { ! 223: ! 224: #define COPYBUFFERSIZE 0x100000 ! 225: ! 226: EFI_STATUS status; ! 227: EFI_FILE* datFile; ! 228: CHAR16 filename[16]; ! 229: UINT32 sz = length; ! 230: UINT8* copyBuffer; ! 231: ! 232: SPrint(filename, sizeof(filename), L"%05x.dat", address); ! 233: status = rootDir->Open(rootDir, &datFile, filename, EFI_FILE_MODE_READ, 0); ! 234: if (!EFI_ERROR(status)) { ! 235: datFile->Delete(datFile); ! 236: datFile->Close(datFile); ! 237: } ! 238: ! 239: status = rootDir->Open(rootDir, &datFile, filename, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0); ! 240: if (EFI_ERROR(status)) { ! 241: Print(L"Open(%s): %r\n", filename, status); ! 242: exit(status); ! 243: } ! 244: ! 245: if (copyFirst) { ! 246: copyBuffer = AllocatePool(COPYBUFFERSIZE); ! 247: if (!copyBuffer) { ! 248: Print(L"Unable to allocate %x byte copy buffer\n", COPYBUFFERSIZE); ! 249: exit(EFI_OUT_OF_RESOURCES); ! 250: } ! 251: } ! 252: ! 253: while (length) { ! 254: UINT8* srcPtr; ! 255: UINT32 sz; ! 256: ! 257: if (copyFirst) { ! 258: sz = length > COPYBUFFERSIZE ? COPYBUFFERSIZE : length; ! 259: __asm mov edi, copyBuffer ! 260: __asm mov esi, address ! 261: __asm mov ecx, sz ! 262: __asm shr ecx, 2 ! 263: __asm rep movsd ! 264: address += sz; ! 265: srcPtr = copyBuffer; ! 266: length -= sz; ! 267: } ! 268: else { ! 269: sz = length; ! 270: srcPtr = (UINT8*)address; ! 271: length = 0; ! 272: } ! 273: Print(L"%X %X %X %X\n", srcPtr, sz, address, length); ! 274: ! 275: status = datFile->Write(datFile, &sz, srcPtr); ! 276: if (EFI_ERROR(status)) { ! 277: Print(L"Write(%s): %r\n", filename, status); ! 278: exit(status); ! 279: } ! 280: } ! 281: ! 282: if (copyFirst) { ! 283: FreePool(copyBuffer); ! 284: } ! 285: ! 286: Print(L"%s, %d bytes\n", filename, length); ! 287: ! 288: datFile->Close(datFile); ! 289: ! 290: } ! 291: ! 292: EFI_FILE* fileOpen(EFI_HANDLE device, CHAR16* filename, UINTN writeable) { ! 293: EFI_FILE* root; ! 294: EFI_FILE* file; ! 295: ! 296: if (device == NULL) ! 297: device = pLoadedImage ? pLoadedImage->DeviceHandle : NULL; ! 298: ! 299: if (device == NULL) { ! 300: Print(L"Invalid device\n"); ! 301: return NULL; ! 302: } ! 303: ! 304: root = LibOpenRoot(device); ! 305: if (root == NULL) ! 306: return root; ! 307: ! 308: status = root->Open(root, &file, filename, EFI_FILE_MODE_READ, 0); ! 309: if (writeable) { ! 310: if (!EFI_ERROR(status)) { ! 311: file->Delete(file); ! 312: file->Close(file); ! 313: } ! 314: ! 315: status = root->Open(root, &file, filename, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0); ! 316: } ! 317: ! 318: if (EFI_ERROR(status)) ! 319: Print(L"Open(%s): %r\n", filename, status); ! 320: root->Close(root); ! 321: ! 322: return file; ! 323: } ! 324: ! 325: EFI_FILE* getFileSystem() { ! 326: UINT32 i, j; ! 327: UINTN handleCount; ! 328: EFI_HANDLE* handles; ! 329: EFI_HANDLE fs[64]; ! 330: EFI_FILE* fileSystem; ! 331: ! 332: // Display all potential storage devices ! 333: LibLocateHandle(ByProtocol, &FileSystemProtocol, NULL, &handleCount, &handles); ! 334: ! 335: for (i = 0, j = 0; i < handleCount && j < sizeof(fs) / sizeof(EFI_HANDLE); ++i) { ! 336: EFI_HANDLE handle = handles[i]; ! 337: EFI_DEVICE_PATH* dpath = DevicePathFromHandle(handle); ! 338: ! 339: if (!dpath) ! 340: continue; ! 341: ! 342: Print(L"%x. %s\n", j + 1, DevicePathToStr(dpath)); ! 343: fs[j++] = handle; ! 344: } ! 345: if (!j) { ! 346: Print(L"No filesystems available\n"); ! 347: exit(EFI_UNSUPPORTED); ! 348: } ! 349: ! 350: // Get the user to choose the filesystem ! 351: do { ! 352: UINT32 i = inputHex(L"Please select the target filesystem ", 1); ! 353: } while (i < 1 || i >= j + 1); ! 354: ! 355: // Open file system ! 356: fileSystem = LibOpenRoot(fs[i - 1]); ! 357: if (!fileSystem) { ! 358: Print(L"Unable to open volume\n"); ! 359: exit(EFI_DEVICE_ERROR); ! 360: } ! 361: ! 362: return fileSystem; ! 363: } ! 364: ! 365: EFI_HANDLE* handleList; ! 366: UINTN maxHandles; ! 367: ! 368: void initHandleList() { ! 369: if (!handleList) { ! 370: LibLocateHandle(AllHandles, NULL, NULL, &maxHandles, &handleList); ! 371: } ! 372: } ! 373: ! 374: EFI_HANDLE getHandleById(UINTN id) { ! 375: initHandleList(); ! 376: ! 377: if (id <= 0 || id > maxHandles) ! 378: exit(EFI_INVALID_PARAMETER); ! 379: ! 380: return handleList[id - 1]; ! 381: } ! 382: ! 383: VOID* getProtocolByHandleId(UINTN id, EFI_GUID* protocol) { ! 384: VOID* if0; ! 385: EFI_HANDLE handle = getHandleById(id); ! 386: ! 387: status = BS->HandleProtocol(handle, protocol, &if0); ! 388: if (EFI_ERROR(status)) ! 389: exit(status); ! 390: return if0; ! 391: } ! 392: ! 393: UINTN getHandleId(EFI_HANDLE handle) { ! 394: UINTN i; ! 395: ! 396: initHandleList(); ! 397: ! 398: for (i = 0; i < maxHandles; ++i) { ! 399: if (handleList[i] == handle) ! 400: return i + 1; ! 401: } ! 402: exit(EFI_INVALID_PARAMETER); ! 403: return 0; ! 404: } ! 405: ! 406: UINT32 getDefaultHexArg(CHAR16* id, UINTN arg, UINT32 dflt) { ! 407: if (arg >= argc) { ! 408: // TODO: Get variable named id and return it if present ! 409: return dflt; ! 410: } ! 411: ! 412: return xtoi(argv[arg]); ! 413: } ! 414: ! 415: CHAR16* getDeviceName(EFI_HANDLE handle) { ! 416: EFI_COMPONENT_NAME_PROTOCOL* pComponentName = NULL; ! 417: CHAR16* pName = NULL; ! 418: EFI_DEVICE_PATH* path; ! 419: ! 420: BS->HandleProtocol(handle, &ComponentNameProtocol, &pComponentName); ! 421: if (pComponentName) ! 422: pComponentName->GetControllerName(pComponentName, handle, NULL, "eng", &pName); ! 423: if (pName) ! 424: return pName; ! 425: ! 426: path = DevicePathFromHandle(handle); ! 427: return path ? DevicePathToStr(path) : L"Unknown"; ! 428: } ! 429: ! 430: void dumpHandles(VOID* protocol) { ! 431: UINTN i, handleCount; ! 432: EFI_HANDLE* handles; ! 433: ! 434: LibLocateHandle(ByProtocol, protocol, NULL, &handleCount, &handles); ! 435: for (i = 0; i < handleCount; ++i) { ! 436: Print(L"%02x: %s\n", getHandleId(handles[i]), getDeviceName(handles[i])); ! 437: } ! 438: } ! 439: ! 440: void dumpHex(VOID* buffer, UINTN bufferOffset, UINTN size, UINTN displayOffset) { ! 441: UINTN lines = (size + 15) / 16; ! 442: UINT8* ptr = ((UINT8*)buffer) + bufferOffset; ! 443: while (lines--) { ! 444: UINTN i; ! 445: ! 446: Print(L"%X: ", displayOffset); ! 447: for (i = 0; i < 15; ++i) { ! 448: if (i < size) ! 449: Print(L"%02x", ptr[i]); ! 450: else ! 451: Print(L" "); ! 452: Print(L"%c", i == 7 ? '-' : ' '); ! 453: } ! 454: ! 455: Print(L" *"); ! 456: for (i = 0; i < 15 && i < size; ++i) { ! 457: CHAR16 c = ptr[i]; ! 458: Print(L"%c", c < 0x20 || c > 0x7f ? '.' : c); ! 459: } ! 460: Print(L"*\n"); ! 461: ! 462: displayOffset += 16; ! 463: ptr += 16; ! 464: size -= 16; ! 465: } ! 466: } ! 467: ! 468: CHAR16 kbdGet() { ! 469: EFI_INPUT_KEY key; ! 470: EFI_STATUS status; ! 471: ! 472: status = pKeyboard->ReadKeyStroke(pKeyboard, &key); ! 473: if (status != EFI_SUCCESS) ! 474: return 0; ! 475: return key.UnicodeChar ? key.UnicodeChar : key.ScanCode | 0x8000; ! 476: } ! 477: ! 478: CHAR16 kbdGetKey() { ! 479: CHAR16 k; ! 480: while (!(k = kbdGet())); ! 481: return k; ! 482: } ! 483: ! 484: void* decompress(void* ptr, UINT32 size) { ! 485: UINT32 destSize, scratchSize; ! 486: VOID* destBuffer; ! 487: VOID* scratchBuffer; ! 488: ! 489: // Get buffer sizes ! 490: status = pDecompress->GetInfo(pDecompress, ptr, size, &destSize, &scratchSize); ! 491: if (EFI_ERROR(status)) { ! 492: Print(L"decompress: Error getting decompress info for %X: %r\n", ptr, status); ! 493: return 0; ! 494: } ! 495: ! 496: // Allocate buffers ! 497: destBuffer = AllocatePool(destSize); ! 498: if (!destBuffer) { ! 499: Print(L"decompress: Unable to allocate %,d bytes for target decompress buffer\n", destSize); ! 500: return 0; ! 501: } ! 502: ! 503: scratchBuffer = AllocatePool(scratchSize); ! 504: if (!scratchBuffer) { ! 505: Print(L"decompress: Unable to allocate %,d bytes for scratch decompress buffer\n", scratchBuffer); ! 506: FreePool(destBuffer); ! 507: return 0; ! 508: } ! 509: ! 510: // Decompress ! 511: status = pDecompress->Decompress(pDecompress, ptr, size, destBuffer, destSize, scratchBuffer, scratchSize); ! 512: if (EFI_ERROR(status)) { ! 513: Print(L"decompress: Error decompressing file at %X: %r\n", ptr, status); ! 514: FreePool(scratchBuffer); ! 515: FreePool(destBuffer); ! 516: return 0; ! 517: } ! 518: ! 519: // Release scratch buffer ! 520: FreePool(scratchBuffer); ! 521: return destBuffer; ! 522: } ! 523: ! 524: void tgaDraw(TGA* tga, UINTN x, UINTN y, TGA_ALIGNMENT alignment) { ! 525: UINTN horizAlign = alignment & tgaHorizontalMask; ! 526: UINTN vertAlign = alignment & tgaVerticalMask; ! 527: ! 528: // See if this is a valid TGA object ! 529: if (tga->colorMapType != 0 || tga->imageType != 2 || tga->bits != 32 || tga->identSize != 0) { ! 530: Print(L"Invalid TGA %X\n", tga); ! 531: return; ! 532: } ! 533: if ((tga->descriptor & 0x20) == 0) { ! 534: static EFI_UGA_PIXEL buffer[2048]; ! 535: UINTN half = tga->height / 2; ! 536: UINTN slSize = tga->width * sizeof(EFI_UGA_PIXEL); ! 537: UINTN y; ! 538: ! 539: for (y = 0; y < half; ++y) { ! 540: void* sl1 = tga->data + y * tga->width; ! 541: void* sl2 = tga->data + (tga->height - y - 1) * tga->width; ! 542: CopyMem(buffer, sl1, slSize); ! 543: CopyMem(sl1 , sl2, slSize); ! 544: CopyMem(sl2, buffer, slSize); ! 545: } ! 546: tga->descriptor |= 0x20; ! 547: } ! 548: x = horizAlign == tgaLeft ? x : ! 549: horizAlign == tgaRight ? x - tga->width : x - tga->width / 2; ! 550: y = vertAlign == tgaTop ? y : ! 551: vertAlign == tgaBottom ? y - tga->height : y - tga->height / 2; ! 552: ! 553: if (pUgaDraw) ! 554: pUgaDraw->Blt(pUgaDraw, tga->data, EfiUgaBltBufferToVideo, 0, 0, x, y, tga->width, tga->height, 0); ! 555: } ! 556: ! 557: CHAR16* StrStr(CHAR16* str, CHAR16* str2) { ! 558: UINTN len, len2, i; ! 559: ! 560: len = StrLen(str); ! 561: len2 = StrLen(str2); ! 562: for (i = 0; i + len2 <= len; ++i) { ! 563: if (!StrnCmp(str + i, str2, len2)) ! 564: return str + i; ! 565: } ! 566: return 0; ! 567: } ! 568: ! 569: int StrEndsWith(CHAR16* str, CHAR16* str2) { ! 570: UINTN len, len2; ! 571: ! 572: len = StrLen(str); ! 573: len2 = StrLen(str2); ! 574: if (len2 > len) ! 575: return 0; ! 576: ! 577: return !StrCmp(str + len - len2, str2); ! 578: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.