Annotation of xom/lib/jlaefi.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.