1/** @file 2Common basic Library Functions 3 4Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR> 5This program and the accompanying materials 6are licensed and made available under the terms and conditions of the BSD License 7which accompanies this distribution. The full text of the license may be found at 8http://opensource.org/licenses/bsd-license.php 9 10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11WITHOUT 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 27VOID 28PeiZeroMem ( 29 IN VOID *Buffer, 30 IN UINTN Size 31 ) 32/*++ 33 34Routine Description: 35 36 Set Buffer to zero for Size bytes. 37 38Arguments: 39 40 Buffer - Memory to set. 41 42 Size - Number of bytes to set 43 44Returns: 45 46 None 47 48--*/ 49{ 50 INT8 *Ptr; 51 52 Ptr = Buffer; 53 while (Size--) { 54 *(Ptr++) = 0; 55 } 56} 57 58VOID 59PeiCopyMem ( 60 IN VOID *Destination, 61 IN VOID *Source, 62 IN UINTN Length 63 ) 64/*++ 65 66Routine Description: 67 68 Copy Length bytes from Source to Destination. 69 70Arguments: 71 72 Destination - Target of copy 73 74 Source - Place to copy from 75 76 Length - Number of bytes to copy 77 78Returns: 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 94VOID 95ZeroMem ( 96 IN VOID *Buffer, 97 IN UINTN Size 98 ) 99{ 100 PeiZeroMem (Buffer, Size); 101} 102 103VOID 104CopyMem ( 105 IN VOID *Destination, 106 IN VOID *Source, 107 IN UINTN Length 108 ) 109{ 110 PeiCopyMem (Destination, Source, Length); 111} 112 113INTN 114CompareGuid ( 115 IN EFI_GUID *Guid1, 116 IN EFI_GUID *Guid2 117 ) 118/*++ 119 120Routine Description: 121 122 Compares to GUIDs 123 124Arguments: 125 126 Guid1 - guid to compare 127 Guid2 - guid to compare 128 129Returns: 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 154EFI_STATUS 155GetFileImage ( 156 IN CHAR8 *InputFileName, 157 OUT CHAR8 **InputFileImage, 158 OUT UINT32 *BytesRead 159 ) 160/*++ 161 162Routine 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 167Arguments: 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 173Returns: 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 256EFI_STATUS 257PutFileImage ( 258 IN CHAR8 *OutputFileName, 259 IN CHAR8 *OutputFileImage, 260 IN UINT32 BytesToWrite 261 ) 262/*++ 263 264Routine Description: 265 266 This function opens a file and writes OutputFileImage into the file. 267 268Arguments: 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 274Returns: 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 321UINT8 322CalculateChecksum8 ( 323 IN UINT8 *Buffer, 324 IN UINTN Size 325 ) 326/*++ 327 328Routine Description: 329 330 This function calculates the value needed for a valid UINT8 checksum 331 332Arguments: 333 334 Buffer Pointer to buffer containing byte data of component. 335 Size Size of the buffer 336 337Returns: 338 339 The 8 bit checksum value needed. 340 341--*/ 342{ 343 return (UINT8) (0x100 - CalculateSum8 (Buffer, Size)); 344} 345 346UINT8 347CalculateSum8 ( 348 IN UINT8 *Buffer, 349 IN UINTN Size 350 ) 351/*++ 352 353Routine Description:: 354 355 This function calculates the UINT8 sum for the requested region. 356 357Arguments: 358 359 Buffer Pointer to buffer containing byte data of component. 360 Size Size of the buffer 361 362Returns: 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 383UINT16 384CalculateChecksum16 ( 385 IN UINT16 *Buffer, 386 IN UINTN Size 387 ) 388/*++ 389 390Routine Description:: 391 392 This function calculates the value needed for a valid UINT16 checksum 393 394Arguments: 395 396 Buffer Pointer to buffer containing byte data of component. 397 Size Size of the buffer 398 399Returns: 400 401 The 16 bit checksum value needed. 402 403--*/ 404{ 405 return (UINT16) (0x10000 - CalculateSum16 (Buffer, Size)); 406} 407 408UINT16 409CalculateSum16 ( 410 IN UINT16 *Buffer, 411 IN UINTN Size 412 ) 413/*++ 414 415Routine Description: 416 417 This function calculates the UINT16 sum for the requested region. 418 419Arguments: 420 421 Buffer Pointer to buffer containing byte data of component. 422 Size Size of the buffer 423 424Returns: 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 445EFI_STATUS 446PrintGuid ( 447 IN EFI_GUID *Guid 448 ) 449/*++ 450 451Routine Description: 452 453 This function prints a GUID to STDOUT. 454 455Arguments: 456 457 Guid Pointer to a GUID to print. 458 459Returns: 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 488EFI_STATUS 489PrintGuidToBuffer ( 490 IN EFI_GUID *Guid, 491 IN OUT UINT8 *Buffer, 492 IN UINT32 BufferLen, 493 IN BOOLEAN Uppercase 494 ) 495/*++ 496 497Routine Description: 498 499 This function prints a GUID to a buffer 500 501Arguments: 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 508Returns: 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 565size_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__ 573char *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// 590CHAR8 mCommonLibFullPath[MAX_LONG_FILE_PATH]; 591 592CHAR8 * 593LongFilePath ( 594 IN CHAR8 *FileName 595 ) 596/*++ 597 598Routine Description: 599 Convert FileName to the long file path, which can support larger than 260 length. 600 601Arguments: 602 FileName - FileName. 603 604Returns: 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 strcat (mCommonLibFullPath, FileName); 656 657 // 658 // Convert directory separator '/' to '\\' 659 // 660 PathPointer = (CHAR8 *) mCommonLibFullPath; 661 do { 662 if (*PathPointer == '/') { 663 *PathPointer = '\\'; 664 } 665 } while (*PathPointer ++ != '\0'); 666 667 // 668 // Convert ":\\\\" to ":\\", because it doesn't work with WINDOWS_EXTENSION_PATH. 669 // 670 if ((PathPointer = strstr (mCommonLibFullPath, ":\\\\")) != NULL) { 671 *(PathPointer + 2) = '\0'; 672 strcat (mCommonLibFullPath, PathPointer + 3); 673 } 674 675 // 676 // Convert ".\\" to "", because it doesn't work with WINDOWS_EXTENSION_PATH. 677 // 678 while ((PathPointer = strstr (mCommonLibFullPath, ".\\")) != NULL) { 679 *PathPointer = '\0'; 680 strcat (mCommonLibFullPath, PathPointer + 2); 681 } 682 683 // 684 // Convert "\\.\\" to "\\", because it doesn't work with WINDOWS_EXTENSION_PATH. 685 // 686 while ((PathPointer = strstr (mCommonLibFullPath, "\\.\\")) != NULL) { 687 *PathPointer = '\0'; 688 strcat (mCommonLibFullPath, PathPointer + 2); 689 } 690 691 // 692 // Convert "\\..\\" to last directory, because it doesn't work with WINDOWS_EXTENSION_PATH. 693 // 694 while ((PathPointer = strstr (mCommonLibFullPath, "\\..\\")) != NULL) { 695 NextPointer = PathPointer + 3; 696 do { 697 PathPointer --; 698 } while (PathPointer > mCommonLibFullPath && *PathPointer != ':' && *PathPointer != '\\'); 699 700 if (*PathPointer == '\\') { 701 // 702 // Skip one directory 703 // 704 *PathPointer = '\0'; 705 strcat (mCommonLibFullPath, NextPointer); 706 } else { 707 // 708 // No directory is found. Just break. 709 // 710 break; 711 } 712 } 713 714 PathPointer = mCommonLibFullPath; 715 } 716 717 return PathPointer; 718#endif 719} 720