1 /** @file 2 Main file for NULL named library for debug1 profile shell command functions. 3 4 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "UefiShellDebug1CommandsLib.h" 16 #include <Library/BcfgCommandLib.h> 17 18 STATIC CONST CHAR16 mFileName[] = L"Debug1Commands"; 19 EFI_HANDLE gShellDebug1HiiHandle = NULL; 20 21 /** 22 Gets the debug file name. This will be used if HII is not working. 23 24 @retval NULL No file is available. 25 @return The NULL-terminated filename to get help from. 26 **/ 27 CONST CHAR16* 28 EFIAPI 29 ShellCommandGetManFileNameDebug1 ( 30 VOID 31 ) 32 { 33 return (mFileName); 34 } 35 36 /** 37 Constructor for the Shell Debug1 Commands library. 38 39 @param ImageHandle the image handle of the process 40 @param SystemTable the EFI System Table pointer 41 42 @retval EFI_SUCCESS the shell command handlers were installed sucessfully 43 @retval EFI_UNSUPPORTED the shell level required was not found. 44 **/ 45 EFI_STATUS 46 EFIAPI 47 UefiShellDebug1CommandsLibConstructor ( 48 IN EFI_HANDLE ImageHandle, 49 IN EFI_SYSTEM_TABLE *SystemTable 50 ) 51 { 52 // 53 // check our bit of the profiles mask 54 // 55 if ((PcdGet8(PcdShellProfileMask) & BIT1) == 0) { 56 return (EFI_SUCCESS); 57 } 58 59 // 60 // install the HII stuff. 61 // 62 gShellDebug1HiiHandle = HiiAddPackages (&gShellDebug1HiiGuid, gImageHandle, UefiShellDebug1CommandsLibStrings, NULL); 63 if (gShellDebug1HiiHandle == NULL) { 64 return (EFI_DEVICE_ERROR); 65 } 66 67 // 68 // install our shell command handlers that are always installed 69 // 70 ShellCommandRegisterCommandName(L"setsize", ShellCommandRunSetSize , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SETSIZE) ); 71 ShellCommandRegisterCommandName(L"comp", ShellCommandRunComp , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_COMP) ); 72 ShellCommandRegisterCommandName(L"mode", ShellCommandRunMode , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MODE) ); 73 ShellCommandRegisterCommandName(L"memmap", ShellCommandRunMemMap , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MEMMAP) ); 74 ShellCommandRegisterCommandName(L"eficompress", ShellCommandRunEfiCompress , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EFICOMPRESS) ); 75 ShellCommandRegisterCommandName(L"efidecompress", ShellCommandRunEfiDecompress , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EFIDCOMPRESS) ); 76 ShellCommandRegisterCommandName(L"dmem", ShellCommandRunDmem , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DMEM) ); 77 ShellCommandRegisterCommandName(L"loadpcirom", ShellCommandRunLoadPciRom , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_LOAD_PCI_ROM) ); 78 ShellCommandRegisterCommandName(L"mm", ShellCommandRunMm , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MM) ); 79 ShellCommandRegisterCommandName(L"setvar", ShellCommandRunSetVar , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SETVAR) ); 80 ShellCommandRegisterCommandName(L"sermode", ShellCommandRunSerMode , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SERMODE) ); 81 ShellCommandRegisterCommandName(L"pci", ShellCommandRunPci , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_PCI) ); 82 ShellCommandRegisterCommandName(L"smbiosview", ShellCommandRunSmbiosView , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SMBIOSVIEW) ); 83 ShellCommandRegisterCommandName(L"dmpstore", ShellCommandRunDmpStore , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DMPSTORE) ); 84 ShellCommandRegisterCommandName(L"dblk", ShellCommandRunDblk , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DBLK) ); 85 ShellCommandRegisterCommandName(L"edit", ShellCommandRunEdit , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EDIT) ); 86 ShellCommandRegisterCommandName(L"hexedit", ShellCommandRunHexEdit , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_HEXEDIT) ); 87 88 ShellCommandRegisterAlias(L"dmem", L"mem"); 89 90 BcfgLibraryRegisterBcfgCommand(ImageHandle, SystemTable, L"Debug1"); 91 92 return (EFI_SUCCESS); 93 } 94 95 /** 96 Destructor for the library. free any resources. 97 98 @param ImageHandle The image handle of the process. 99 @param SystemTable The EFI System Table pointer. 100 **/ 101 EFI_STATUS 102 EFIAPI 103 UefiShellDebug1CommandsLibDestructor ( 104 IN EFI_HANDLE ImageHandle, 105 IN EFI_SYSTEM_TABLE *SystemTable 106 ) 107 { 108 if (gShellDebug1HiiHandle != NULL) { 109 HiiRemovePackages(gShellDebug1HiiHandle); 110 } 111 112 BcfgLibraryUnregisterBcfgCommand(ImageHandle, SystemTable); 113 return (EFI_SUCCESS); 114 } 115 116 /** 117 Convert a Unicode character to upper case only if 118 it maps to a valid small-case ASCII character. 119 120 This internal function only deal with Unicode character 121 which maps to a valid small-case ASCII character, i.e. 122 L'a' to L'z'. For other Unicode character, the input character 123 is returned directly. 124 125 @param Char The character to convert. 126 127 @retval LowerCharacter If the Char is with range L'a' to L'z'. 128 @retval Unchanged Otherwise. 129 130 131 //Stolen from MdePkg Baselib 132 **/ 133 CHAR16 134 CharToUpper ( 135 IN CHAR16 Char 136 ) 137 { 138 if (Char >= L'a' && Char <= L'z') { 139 return (CHAR16) (Char - (L'a' - L'A')); 140 } 141 142 return Char; 143 } 144 145 /** 146 Function returns a system configuration table that is stored in the 147 EFI System Table based on the provided GUID. 148 149 @param[in] TableGuid A pointer to the table's GUID type. 150 @param[in, out] Table On exit, a pointer to a system configuration table. 151 152 @retval EFI_SUCCESS A configuration table matching TableGuid was found. 153 @retval EFI_NOT_FOUND A configuration table matching TableGuid was not found. 154 **/ 155 EFI_STATUS 156 GetSystemConfigurationTable ( 157 IN EFI_GUID *TableGuid, 158 IN OUT VOID **Table 159 ) 160 { 161 UINTN Index; 162 ASSERT (Table != NULL); 163 164 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) { 165 if (CompareGuid (TableGuid, &(gST->ConfigurationTable[Index].VendorGuid))) { 166 *Table = gST->ConfigurationTable[Index].VendorTable; 167 return EFI_SUCCESS; 168 } 169 } 170 171 return EFI_NOT_FOUND; 172 } 173 174 /** 175 Convert a Unicode character to numerical value. 176 177 This internal function only deal with Unicode character 178 which maps to a valid hexadecimal ASII character, i.e. 179 L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other 180 Unicode character, the value returned does not make sense. 181 182 @param Char The character to convert. 183 184 @return The numerical value converted. 185 186 **/ 187 UINTN 188 HexCharToUintn ( 189 IN CHAR16 Char 190 ) 191 { 192 if (Char >= L'0' && Char <= L'9') { 193 return Char - L'0'; 194 } 195 196 return (UINTN) (10 + CharToUpper (Char) - L'A'); 197 } 198 199 /** 200 Convert a string representation of a guid to a Guid value. 201 202 @param[in] StringGuid The pointer to the string of a guid. 203 @param[in, out] Guid The pointer to the GUID structure to populate. 204 205 @retval EFI_INVALID_PARAMETER A parameter was invalid. 206 @retval EFI_SUCCESS The conversion was successful. 207 **/ 208 EFI_STATUS 209 ConvertStringToGuid ( 210 IN CONST CHAR16 *StringGuid, 211 IN OUT EFI_GUID *Guid 212 ) 213 { 214 CHAR16 *TempCopy; 215 CHAR16 *TempSpot; 216 CHAR16 *Walker; 217 UINT64 TempVal; 218 EFI_STATUS Status; 219 220 if (StringGuid == NULL) { 221 return (EFI_INVALID_PARAMETER); 222 } else if (StrLen(StringGuid) != 36) { 223 return (EFI_INVALID_PARAMETER); 224 } 225 TempCopy = NULL; 226 TempCopy = StrnCatGrow(&TempCopy, NULL, StringGuid, 0); 227 if (TempCopy == NULL) { 228 return (EFI_OUT_OF_RESOURCES); 229 } 230 Walker = TempCopy; 231 TempSpot = StrStr(Walker, L"-"); 232 if (TempSpot != NULL) { 233 *TempSpot = CHAR_NULL; 234 } 235 Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE); 236 if (EFI_ERROR(Status)) { 237 FreePool(TempCopy); 238 return (Status); 239 } 240 Guid->Data1 = (UINT32)TempVal; 241 Walker += 9; 242 TempSpot = StrStr(Walker, L"-"); 243 if (TempSpot != NULL) { 244 *TempSpot = CHAR_NULL; 245 } 246 Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE); 247 if (EFI_ERROR(Status)) { 248 FreePool(TempCopy); 249 return (Status); 250 } 251 Guid->Data2 = (UINT16)TempVal; 252 Walker += 5; 253 TempSpot = StrStr(Walker, L"-"); 254 if (TempSpot != NULL) { 255 *TempSpot = CHAR_NULL; 256 } 257 Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE); 258 if (EFI_ERROR(Status)) { 259 FreePool(TempCopy); 260 return (Status); 261 } 262 Guid->Data3 = (UINT16)TempVal; 263 Walker += 5; 264 Guid->Data4[0] = (UINT8)(HexCharToUintn(Walker[0]) * 16); 265 Guid->Data4[0] = (UINT8)(Guid->Data4[0]+ (UINT8)HexCharToUintn(Walker[1])); 266 Walker += 2; 267 Guid->Data4[1] = (UINT8)(HexCharToUintn(Walker[0]) * 16); 268 Guid->Data4[1] = (UINT8)(Guid->Data4[1] + (UINT8)HexCharToUintn(Walker[1])); 269 Walker += 3; 270 Guid->Data4[2] = (UINT8)(HexCharToUintn(Walker[0]) * 16); 271 Guid->Data4[2] = (UINT8)(Guid->Data4[2] + (UINT8)HexCharToUintn(Walker[1])); 272 Walker += 2; 273 Guid->Data4[3] = (UINT8)(HexCharToUintn(Walker[0]) * 16); 274 Guid->Data4[3] = (UINT8)(Guid->Data4[3] + (UINT8)HexCharToUintn(Walker[1])); 275 Walker += 2; 276 Guid->Data4[4] = (UINT8)(HexCharToUintn(Walker[0]) * 16); 277 Guid->Data4[4] = (UINT8)(Guid->Data4[4] + (UINT8)HexCharToUintn(Walker[1])); 278 Walker += 2; 279 Guid->Data4[5] = (UINT8)(HexCharToUintn(Walker[0]) * 16); 280 Guid->Data4[5] = (UINT8)(Guid->Data4[5] + (UINT8)HexCharToUintn(Walker[1])); 281 Walker += 2; 282 Guid->Data4[6] = (UINT8)(HexCharToUintn(Walker[0]) * 16); 283 Guid->Data4[6] = (UINT8)(Guid->Data4[6] + (UINT8)HexCharToUintn(Walker[1])); 284 Walker += 2; 285 Guid->Data4[7] = (UINT8)(HexCharToUintn(Walker[0]) * 16); 286 Guid->Data4[7] = (UINT8)(Guid->Data4[7] + (UINT8)HexCharToUintn(Walker[1])); 287 FreePool(TempCopy); 288 return (EFI_SUCCESS); 289 } 290 291 /** 292 Clear the line at the specified Row. 293 294 @param[in] Row The row number to be cleared ( start from 1 ) 295 @param[in] LastCol The last printable column. 296 @param[in] LastRow The last printable row. 297 **/ 298 VOID 299 EditorClearLine ( 300 IN UINTN Row, 301 IN UINTN LastCol, 302 IN UINTN LastRow 303 ) 304 { 305 CHAR16 Line[200]; 306 307 if (Row == 0) { 308 Row = 1; 309 } 310 311 // 312 // prepare a blank line 313 // 314 SetMem16(Line, LastCol*sizeof(CHAR16), L' '); 315 316 if (Row == LastRow) { 317 // 318 // if CHAR_NULL is still at position 80, it will cause first line error 319 // 320 Line[LastCol - 1] = CHAR_NULL; 321 } else { 322 Line[LastCol] = CHAR_NULL; 323 } 324 325 // 326 // print out the blank line 327 // 328 ShellPrintEx (0, ((INT32)Row) - 1, Line); 329 } 330 331 /** 332 Determine if the character is valid for a filename. 333 334 @param[in] Ch The character to test. 335 336 @retval TRUE The character is valid. 337 @retval FALSE The character is not valid. 338 **/ 339 BOOLEAN 340 IsValidFileNameChar ( 341 IN CONST CHAR16 Ch 342 ) 343 { 344 // 345 // See if there are any illegal characters within the name 346 // 347 if (Ch < 0x20 || Ch == L'\"' || Ch == L'*' || Ch == L'/' || Ch == L'<' || Ch == L'>' || Ch == L'?' || Ch == L'|') { 348 return FALSE; 349 } 350 351 return TRUE; 352 } 353 354 /** 355 Check if file name has illegal characters. 356 357 @param Name The filename to check. 358 359 @retval TRUE The filename is ok. 360 @retval FALSE The filename is not ok. 361 **/ 362 BOOLEAN 363 IsValidFileName ( 364 IN CONST CHAR16 *Name 365 ) 366 { 367 368 UINTN Index; 369 UINTN Len; 370 371 // 372 // check the length of Name 373 // 374 for (Len = 0, Index = StrLen (Name) - 1; Index + 1 != 0; Index--, Len++) { 375 if (Name[Index] == '\\' || Name[Index] == ':') { 376 break; 377 } 378 } 379 380 if (Len == 0 || Len > 255) { 381 return FALSE; 382 } 383 // 384 // check whether any char in Name not appears in valid file name char 385 // 386 for (Index = 0; Index < StrLen (Name); Index++) { 387 if (!IsValidFileNameChar (Name[Index])) { 388 return FALSE; 389 } 390 } 391 392 return TRUE; 393 } 394 395 /** 396 Find a filename that is valid (not taken) with the given extension. 397 398 @param[in] Extension The file extension. 399 400 @retval NULL Something went wrong. 401 @return the valid filename. 402 **/ 403 CHAR16 * 404 EditGetDefaultFileName ( 405 IN CONST CHAR16 *Extension 406 ) 407 { 408 EFI_STATUS Status; 409 UINTN Suffix; 410 CHAR16 *FileNameTmp; 411 412 Suffix = 0; 413 414 do { 415 FileNameTmp = CatSPrint (NULL, L"NewFile%d.%s", Suffix, Extension); 416 417 // 418 // after that filename changed to path 419 // 420 Status = ShellFileExists (FileNameTmp); 421 422 if (Status == EFI_NOT_FOUND) { 423 return FileNameTmp; 424 } 425 426 FreePool (FileNameTmp); 427 FileNameTmp = NULL; 428 Suffix++; 429 } while (Suffix != 0); 430 431 FreePool (FileNameTmp); 432 return NULL; 433 } 434 435 /** 436 Read a file into an allocated buffer. The buffer is the responsibility 437 of the caller to free. 438 439 @param[in] FileName The filename of the file to open. 440 @param[out] Buffer Upon successful return, the pointer to the 441 address of the allocated buffer. 442 @param[out] BufferSize If not NULL, then the pointer to the size 443 of the allocated buffer. 444 @param[out] ReadOnly Upon successful return TRUE if the file is 445 read only. FALSE otherwise. 446 447 @retval EFI_NOT_FOUND The filename did not represent a file in the 448 file system. 449 @retval EFI_SUCCESS The file was read into the buffer. 450 @retval EFI_OUT_OF_RESOURCES A memory allocation failed. 451 @retval EFI_LOAD_ERROR The file read operation failed. 452 @retval EFI_INVALID_PARAMETER A parameter was invalid. 453 @retval EFI_INVALID_PARAMETER FileName was NULL. 454 @retval EFI_INVALID_PARAMETER FileName was a directory. 455 **/ 456 EFI_STATUS 457 ReadFileIntoBuffer ( 458 IN CONST CHAR16 *FileName, 459 OUT VOID **Buffer, 460 OUT UINTN *BufferSize OPTIONAL, 461 OUT BOOLEAN *ReadOnly 462 ) 463 { 464 VOID *InternalBuffer; 465 UINTN FileSize; 466 SHELL_FILE_HANDLE FileHandle; 467 BOOLEAN CreateFile; 468 EFI_STATUS Status; 469 EFI_FILE_INFO *Info; 470 471 InternalBuffer = NULL; 472 FileSize = 0; 473 FileHandle = NULL; 474 CreateFile = FALSE; 475 Status = EFI_SUCCESS; 476 Info = NULL; 477 478 if (FileName == NULL || Buffer == NULL || ReadOnly == NULL) { 479 return (EFI_INVALID_PARAMETER); 480 } 481 482 // 483 // try to open the file 484 // 485 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0); 486 487 if (!EFI_ERROR(Status)) { 488 ASSERT(CreateFile == FALSE); 489 if (FileHandle == NULL) { 490 return EFI_LOAD_ERROR; 491 } 492 493 Info = ShellGetFileInfo(FileHandle); 494 495 if (Info->Attribute & EFI_FILE_DIRECTORY) { 496 FreePool (Info); 497 return EFI_INVALID_PARAMETER; 498 } 499 500 if (Info->Attribute & EFI_FILE_READ_ONLY) { 501 *ReadOnly = TRUE; 502 } else { 503 *ReadOnly = FALSE; 504 } 505 // 506 // get file size 507 // 508 FileSize = (UINTN) Info->FileSize; 509 510 FreePool (Info); 511 } else if (Status == EFI_NOT_FOUND) { 512 // 513 // file not exists. add create and try again 514 // 515 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); 516 if (EFI_ERROR (Status)) { 517 return Status; 518 } else { 519 // 520 // it worked. now delete it and move on with the name (now validated) 521 // 522 Status = ShellDeleteFile (&FileHandle); 523 if (Status == EFI_WARN_DELETE_FAILURE) { 524 Status = EFI_ACCESS_DENIED; 525 } 526 if (EFI_ERROR (Status)) { 527 return Status; 528 } 529 } 530 // 531 // file doesn't exist, so set CreateFile to TRUE and can't be read-only 532 // 533 CreateFile = TRUE; 534 *ReadOnly = FALSE; 535 } 536 537 // 538 // the file exists 539 // 540 if (!CreateFile) { 541 // 542 // allocate buffer to read file 543 // 544 InternalBuffer = AllocateZeroPool (FileSize); 545 if (InternalBuffer == NULL) { 546 return EFI_OUT_OF_RESOURCES; 547 } 548 // 549 // read file into InternalBuffer 550 // 551 Status = ShellReadFile (FileHandle, &FileSize, InternalBuffer); 552 ShellCloseFile(&FileHandle); 553 FileHandle = NULL; 554 if (EFI_ERROR (Status)) { 555 SHELL_FREE_NON_NULL (InternalBuffer); 556 return EFI_LOAD_ERROR; 557 } 558 } 559 *Buffer = InternalBuffer; 560 if (BufferSize != NULL) { 561 *BufferSize = FileSize; 562 } 563 return (EFI_SUCCESS); 564 565 } 566