1 /** @file 2 Common basic Library Functions 3 4 Copyright (c) 2004 - 2016, 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 <stdio.h> 16 #include <string.h> 17 #include <stdlib.h> 18 #include <ctype.h> 19 #ifdef __GNUC__ 20 #include <unistd.h> 21 #else 22 #include <direct.h> 23 #endif 24 #include "CommonLib.h" 25 #include "EfiUtilityMsgs.h" 26 27 VOID 28 PeiZeroMem ( 29 IN VOID *Buffer, 30 IN UINTN Size 31 ) 32 /*++ 33 34 Routine Description: 35 36 Set Buffer to zero for Size bytes. 37 38 Arguments: 39 40 Buffer - Memory to set. 41 42 Size - Number of bytes to set 43 44 Returns: 45 46 None 47 48 --*/ 49 { 50 INT8 *Ptr; 51 52 Ptr = Buffer; 53 while (Size--) { 54 *(Ptr++) = 0; 55 } 56 } 57 58 VOID 59 PeiCopyMem ( 60 IN VOID *Destination, 61 IN VOID *Source, 62 IN UINTN Length 63 ) 64 /*++ 65 66 Routine Description: 67 68 Copy Length bytes from Source to Destination. 69 70 Arguments: 71 72 Destination - Target of copy 73 74 Source - Place to copy from 75 76 Length - Number of bytes to copy 77 78 Returns: 79 80 None 81 82 --*/ 83 { 84 CHAR8 *Destination8; 85 CHAR8 *Source8; 86 87 Destination8 = Destination; 88 Source8 = Source; 89 while (Length--) { 90 *(Destination8++) = *(Source8++); 91 } 92 } 93 94 VOID 95 ZeroMem ( 96 IN VOID *Buffer, 97 IN UINTN Size 98 ) 99 { 100 PeiZeroMem (Buffer, Size); 101 } 102 103 VOID 104 CopyMem ( 105 IN VOID *Destination, 106 IN VOID *Source, 107 IN UINTN Length 108 ) 109 { 110 PeiCopyMem (Destination, Source, Length); 111 } 112 113 INTN 114 CompareGuid ( 115 IN EFI_GUID *Guid1, 116 IN EFI_GUID *Guid2 117 ) 118 /*++ 119 120 Routine Description: 121 122 Compares to GUIDs 123 124 Arguments: 125 126 Guid1 - guid to compare 127 Guid2 - guid to compare 128 129 Returns: 130 = 0 if Guid1 == Guid2 131 != 0 if Guid1 != Guid2 132 133 --*/ 134 { 135 INT32 *g1; 136 INT32 *g2; 137 INT32 r; 138 139 // 140 // Compare 32 bits at a time 141 // 142 g1 = (INT32 *) Guid1; 143 g2 = (INT32 *) Guid2; 144 145 r = g1[0] - g2[0]; 146 r |= g1[1] - g2[1]; 147 r |= g1[2] - g2[2]; 148 r |= g1[3] - g2[3]; 149 150 return r; 151 } 152 153 154 EFI_STATUS 155 GetFileImage ( 156 IN CHAR8 *InputFileName, 157 OUT CHAR8 **InputFileImage, 158 OUT UINT32 *BytesRead 159 ) 160 /*++ 161 162 Routine Description: 163 164 This function opens a file and reads it into a memory buffer. The function 165 will allocate the memory buffer and returns the size of the buffer. 166 167 Arguments: 168 169 InputFileName The name of the file to read. 170 InputFileImage A pointer to the memory buffer. 171 BytesRead The size of the memory buffer. 172 173 Returns: 174 175 EFI_SUCCESS The function completed successfully. 176 EFI_INVALID_PARAMETER One of the input parameters was invalid. 177 EFI_ABORTED An error occurred. 178 EFI_OUT_OF_RESOURCES No resource to complete operations. 179 180 --*/ 181 { 182 FILE *InputFile; 183 UINT32 FileSize; 184 185 // 186 // Verify input parameters. 187 // 188 if (InputFileName == NULL || strlen (InputFileName) == 0 || InputFileImage == NULL) { 189 return EFI_INVALID_PARAMETER; 190 } 191 // 192 // Open the file and copy contents into a memory buffer. 193 // 194 // 195 // Open the file 196 // 197 InputFile = fopen (LongFilePath (InputFileName), "rb"); 198 if (InputFile == NULL) { 199 Error (NULL, 0, 0001, "Error opening the input file", InputFileName); 200 return EFI_ABORTED; 201 } 202 // 203 // Go to the end so that we can determine the file size 204 // 205 if (fseek (InputFile, 0, SEEK_END)) { 206 Error (NULL, 0, 0004, "Error reading the input file", InputFileName); 207 fclose (InputFile); 208 return EFI_ABORTED; 209 } 210 // 211 // Get the file size 212 // 213 FileSize = ftell (InputFile); 214 if (FileSize == -1) { 215 Error (NULL, 0, 0003, "Error parsing the input file", InputFileName); 216 fclose (InputFile); 217 return EFI_ABORTED; 218 } 219 // 220 // Allocate a buffer 221 // 222 *InputFileImage = malloc (FileSize); 223 if (*InputFileImage == NULL) { 224 fclose (InputFile); 225 return EFI_OUT_OF_RESOURCES; 226 } 227 // 228 // Reset to the beginning of the file 229 // 230 if (fseek (InputFile, 0, SEEK_SET)) { 231 Error (NULL, 0, 0004, "Error reading the input file", InputFileName); 232 fclose (InputFile); 233 free (*InputFileImage); 234 *InputFileImage = NULL; 235 return EFI_ABORTED; 236 } 237 // 238 // Read all of the file contents. 239 // 240 *BytesRead = fread (*InputFileImage, sizeof (UINT8), FileSize, InputFile); 241 if (*BytesRead != sizeof (UINT8) * FileSize) { 242 Error (NULL, 0, 0004, "Error reading the input file", InputFileName); 243 fclose (InputFile); 244 free (*InputFileImage); 245 *InputFileImage = NULL; 246 return EFI_ABORTED; 247 } 248 // 249 // Close the file 250 // 251 fclose (InputFile); 252 253 return EFI_SUCCESS; 254 } 255 256 EFI_STATUS 257 PutFileImage ( 258 IN CHAR8 *OutputFileName, 259 IN CHAR8 *OutputFileImage, 260 IN UINT32 BytesToWrite 261 ) 262 /*++ 263 264 Routine Description: 265 266 This function opens a file and writes OutputFileImage into the file. 267 268 Arguments: 269 270 OutputFileName The name of the file to write. 271 OutputFileImage A pointer to the memory buffer. 272 BytesToWrite The size of the memory buffer. 273 274 Returns: 275 276 EFI_SUCCESS The function completed successfully. 277 EFI_INVALID_PARAMETER One of the input parameters was invalid. 278 EFI_ABORTED An error occurred. 279 EFI_OUT_OF_RESOURCES No resource to complete operations. 280 281 --*/ 282 { 283 FILE *OutputFile; 284 UINT32 BytesWrote; 285 286 // 287 // Verify input parameters. 288 // 289 if (OutputFileName == NULL || strlen (OutputFileName) == 0 || OutputFileImage == NULL) { 290 return EFI_INVALID_PARAMETER; 291 } 292 // 293 // Open the file and copy contents into a memory buffer. 294 // 295 // 296 // Open the file 297 // 298 OutputFile = fopen (LongFilePath (OutputFileName), "wb"); 299 if (OutputFile == NULL) { 300 Error (NULL, 0, 0001, "Error opening the output file", OutputFileName); 301 return EFI_ABORTED; 302 } 303 304 // 305 // Write all of the file contents. 306 // 307 BytesWrote = fwrite (OutputFileImage, sizeof (UINT8), BytesToWrite, OutputFile); 308 if (BytesWrote != sizeof (UINT8) * BytesToWrite) { 309 Error (NULL, 0, 0002, "Error writing the output file", OutputFileName); 310 fclose (OutputFile); 311 return EFI_ABORTED; 312 } 313 // 314 // Close the file 315 // 316 fclose (OutputFile); 317 318 return EFI_SUCCESS; 319 } 320 321 UINT8 322 CalculateChecksum8 ( 323 IN UINT8 *Buffer, 324 IN UINTN Size 325 ) 326 /*++ 327 328 Routine Description: 329 330 This function calculates the value needed for a valid UINT8 checksum 331 332 Arguments: 333 334 Buffer Pointer to buffer containing byte data of component. 335 Size Size of the buffer 336 337 Returns: 338 339 The 8 bit checksum value needed. 340 341 --*/ 342 { 343 return (UINT8) (0x100 - CalculateSum8 (Buffer, Size)); 344 } 345 346 UINT8 347 CalculateSum8 ( 348 IN UINT8 *Buffer, 349 IN UINTN Size 350 ) 351 /*++ 352 353 Routine Description:: 354 355 This function calculates the UINT8 sum for the requested region. 356 357 Arguments: 358 359 Buffer Pointer to buffer containing byte data of component. 360 Size Size of the buffer 361 362 Returns: 363 364 The 8 bit checksum value needed. 365 366 --*/ 367 { 368 UINTN Index; 369 UINT8 Sum; 370 371 Sum = 0; 372 373 // 374 // Perform the byte sum for buffer 375 // 376 for (Index = 0; Index < Size; Index++) { 377 Sum = (UINT8) (Sum + Buffer[Index]); 378 } 379 380 return Sum; 381 } 382 383 UINT16 384 CalculateChecksum16 ( 385 IN UINT16 *Buffer, 386 IN UINTN Size 387 ) 388 /*++ 389 390 Routine Description:: 391 392 This function calculates the value needed for a valid UINT16 checksum 393 394 Arguments: 395 396 Buffer Pointer to buffer containing byte data of component. 397 Size Size of the buffer 398 399 Returns: 400 401 The 16 bit checksum value needed. 402 403 --*/ 404 { 405 return (UINT16) (0x10000 - CalculateSum16 (Buffer, Size)); 406 } 407 408 UINT16 409 CalculateSum16 ( 410 IN UINT16 *Buffer, 411 IN UINTN Size 412 ) 413 /*++ 414 415 Routine Description: 416 417 This function calculates the UINT16 sum for the requested region. 418 419 Arguments: 420 421 Buffer Pointer to buffer containing byte data of component. 422 Size Size of the buffer 423 424 Returns: 425 426 The 16 bit checksum 427 428 --*/ 429 { 430 UINTN Index; 431 UINT16 Sum; 432 433 Sum = 0; 434 435 // 436 // Perform the word sum for buffer 437 // 438 for (Index = 0; Index < Size; Index++) { 439 Sum = (UINT16) (Sum + Buffer[Index]); 440 } 441 442 return (UINT16) Sum; 443 } 444 445 EFI_STATUS 446 PrintGuid ( 447 IN EFI_GUID *Guid 448 ) 449 /*++ 450 451 Routine Description: 452 453 This function prints a GUID to STDOUT. 454 455 Arguments: 456 457 Guid Pointer to a GUID to print. 458 459 Returns: 460 461 EFI_SUCCESS The GUID was printed. 462 EFI_INVALID_PARAMETER The input was NULL. 463 464 --*/ 465 { 466 if (Guid == NULL) { 467 Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value"); 468 return EFI_INVALID_PARAMETER; 469 } 470 471 printf ( 472 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", 473 (unsigned) Guid->Data1, 474 Guid->Data2, 475 Guid->Data3, 476 Guid->Data4[0], 477 Guid->Data4[1], 478 Guid->Data4[2], 479 Guid->Data4[3], 480 Guid->Data4[4], 481 Guid->Data4[5], 482 Guid->Data4[6], 483 Guid->Data4[7] 484 ); 485 return EFI_SUCCESS; 486 } 487 488 EFI_STATUS 489 PrintGuidToBuffer ( 490 IN EFI_GUID *Guid, 491 IN OUT UINT8 *Buffer, 492 IN UINT32 BufferLen, 493 IN BOOLEAN Uppercase 494 ) 495 /*++ 496 497 Routine Description: 498 499 This function prints a GUID to a buffer 500 501 Arguments: 502 503 Guid - Pointer to a GUID to print. 504 Buffer - Pointer to a user-provided buffer to print to 505 BufferLen - Size of the Buffer 506 Uppercase - If use upper case. 507 508 Returns: 509 510 EFI_SUCCESS The GUID was printed. 511 EFI_INVALID_PARAMETER The input was NULL. 512 EFI_BUFFER_TOO_SMALL The input buffer was not big enough 513 514 --*/ 515 { 516 if (Guid == NULL) { 517 Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value"); 518 return EFI_INVALID_PARAMETER; 519 } 520 521 if (BufferLen < PRINTED_GUID_BUFFER_SIZE) { 522 Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with invalid buffer size"); 523 return EFI_BUFFER_TOO_SMALL; 524 } 525 526 if (Uppercase) { 527 sprintf ( 528 (CHAR8 *)Buffer, 529 "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", 530 (unsigned) Guid->Data1, 531 Guid->Data2, 532 Guid->Data3, 533 Guid->Data4[0], 534 Guid->Data4[1], 535 Guid->Data4[2], 536 Guid->Data4[3], 537 Guid->Data4[4], 538 Guid->Data4[5], 539 Guid->Data4[6], 540 Guid->Data4[7] 541 ); 542 } else { 543 sprintf ( 544 (CHAR8 *)Buffer, 545 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 546 (unsigned) Guid->Data1, 547 Guid->Data2, 548 Guid->Data3, 549 Guid->Data4[0], 550 Guid->Data4[1], 551 Guid->Data4[2], 552 Guid->Data4[3], 553 Guid->Data4[4], 554 Guid->Data4[5], 555 Guid->Data4[6], 556 Guid->Data4[7] 557 ); 558 } 559 560 return EFI_SUCCESS; 561 } 562 563 #ifdef __GNUC__ 564 565 size_t _filelength(int fd) 566 { 567 struct stat stat_buf; 568 fstat(fd, &stat_buf); 569 return stat_buf.st_size; 570 } 571 572 #ifndef __CYGWIN__ 573 char *strlwr(char *s) 574 { 575 char *p = s; 576 for(;*s;s++) { 577 *s = tolower(*s); 578 } 579 return p; 580 } 581 #endif 582 #endif 583 584 #define WINDOWS_EXTENSION_PATH "\\\\?\\" 585 #define WINDOWS_UNC_EXTENSION_PATH "\\\\?\\UNC" 586 587 // 588 // Global data to store full file path. It is not required to be free. 589 // 590 CHAR8 mCommonLibFullPath[MAX_LONG_FILE_PATH]; 591 592 CHAR8 * 593 LongFilePath ( 594 IN CHAR8 *FileName 595 ) 596 /*++ 597 598 Routine Description: 599 Convert FileName to the long file path, which can support larger than 260 length. 600 601 Arguments: 602 FileName - FileName. 603 604 Returns: 605 LongFilePath A pointer to the converted long file path. 606 607 --*/ 608 { 609 #ifdef __GNUC__ 610 // 611 // __GNUC__ may not be good way to differentiate unix and windows. Need more investigation here. 612 // unix has no limitation on file path. Just return FileName. 613 // 614 return FileName; 615 #else 616 CHAR8 *RootPath; 617 CHAR8 *PathPointer; 618 CHAR8 *NextPointer; 619 620 PathPointer = (CHAR8 *) FileName; 621 622 if (FileName != NULL) { 623 // 624 // Add the extension string first to support long file path. 625 // 626 mCommonLibFullPath[0] = 0; 627 strcpy (mCommonLibFullPath, WINDOWS_EXTENSION_PATH); 628 629 if (strlen (FileName) > 1 && FileName[0] == '\\' && FileName[1] == '\\') { 630 // 631 // network path like \\server\share to \\?\UNC\server\share 632 // 633 strcpy (mCommonLibFullPath, WINDOWS_UNC_EXTENSION_PATH); 634 FileName ++; 635 } else if (strlen (FileName) < 3 || FileName[1] != ':' || (FileName[2] != '\\' && FileName[2] != '/')) { 636 // 637 // Relative file path. Convert it to absolute path. 638 // 639 RootPath = getcwd (NULL, 0); 640 if (RootPath != NULL) { 641 strcat (mCommonLibFullPath, RootPath); 642 if (FileName[0] != '\\' && FileName[0] != '/') { 643 // 644 // Attach directory separator 645 // 646 strcat (mCommonLibFullPath, "\\"); 647 } 648 free (RootPath); 649 } 650 } 651 652 // 653 // Construct the full file path 654 // 655 if (strlen (mCommonLibFullPath) + strlen (FileName) > MAX_LONG_FILE_PATH - 1) { 656 Error (NULL, 0, 2000, "Invalid parameter", "FileName %s is too long!", FileName); 657 return NULL; 658 } 659 strncat (mCommonLibFullPath, FileName, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1); 660 661 // 662 // Convert directory separator '/' to '\\' 663 // 664 PathPointer = (CHAR8 *) mCommonLibFullPath; 665 do { 666 if (*PathPointer == '/') { 667 *PathPointer = '\\'; 668 } 669 } while (*PathPointer ++ != '\0'); 670 671 // 672 // Convert ":\\\\" to ":\\", because it doesn't work with WINDOWS_EXTENSION_PATH. 673 // 674 if ((PathPointer = strstr (mCommonLibFullPath, ":\\\\")) != NULL) { 675 *(PathPointer + 2) = '\0'; 676 strcat (mCommonLibFullPath, PathPointer + 3); 677 } 678 679 // 680 // Convert ".\\" to "", because it doesn't work with WINDOWS_EXTENSION_PATH. 681 // 682 while ((PathPointer = strstr (mCommonLibFullPath, ".\\")) != NULL) { 683 *PathPointer = '\0'; 684 strcat (mCommonLibFullPath, PathPointer + 2); 685 } 686 687 // 688 // Convert "\\.\\" to "\\", because it doesn't work with WINDOWS_EXTENSION_PATH. 689 // 690 while ((PathPointer = strstr (mCommonLibFullPath, "\\.\\")) != NULL) { 691 *PathPointer = '\0'; 692 strcat (mCommonLibFullPath, PathPointer + 2); 693 } 694 695 // 696 // Convert "\\..\\" to last directory, because it doesn't work with WINDOWS_EXTENSION_PATH. 697 // 698 while ((PathPointer = strstr (mCommonLibFullPath, "\\..\\")) != NULL) { 699 NextPointer = PathPointer + 3; 700 do { 701 PathPointer --; 702 } while (PathPointer > mCommonLibFullPath && *PathPointer != ':' && *PathPointer != '\\'); 703 704 if (*PathPointer == '\\') { 705 // 706 // Skip one directory 707 // 708 *PathPointer = '\0'; 709 strcat (mCommonLibFullPath, NextPointer); 710 } else { 711 // 712 // No directory is found. Just break. 713 // 714 break; 715 } 716 } 717 718 PathPointer = mCommonLibFullPath; 719 } 720 721 return PathPointer; 722 #endif 723 } 724