FreePages.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*
  2. * Copyright (C) 2013 Jerry Hoemann <jerry.hoemann@hp.com>
  3. *
  4. * Application to allocate memory at EFI. Syntax of command
  5. * mimics the EFI Boot Service "FreePages."
  6. *
  7. * See UEFI spec 2.3, Section 6.2.
  8. *
  9. Example freeing a 5 page BS_Code setment at address: 0000000020000000 (hex)
  10. FS1:\> memmap
  11. Type Start End #pages Attributes
  12. BS_Code 0000000000000000-0000000000000FFF 0000000000000001 000000000000000F
  13. Available 0000000000001000-000000000008DFFF 000000000000008D 000000000000000F
  14. Reserved 000000000008E000-000000000008FFFF 0000000000000002 000000000000000F
  15. Available 0000000000090000-000000000009FFFF 0000000000000010 000000000000000F
  16. Available 0000000000100000-000000000FFFFFFF 000000000000FF00 000000000000000F
  17. BS_Code 0000000010000000-0000000010061FFF 0000000000000062 000000000000000F
  18. Available 0000000010062000-000000001FFFFFFF 000000000000FF9E 000000000000000F
  19. BS_Code 0000000020000000-0000000020004FFF 0000000000000005 000000000000000F
  20. Available 0000000020005000-000000005DDFFFFF 000000000003DDFB 000000000000000F
  21. BS_Data 000000005DE00000-000000005DFFFFFF 0000000000000200 000000000000000F
  22. Available 000000005E000000-000000006DE7CFFF 000000000000FE7D 000000000000000F
  23. ACPI_NVS 000000006DE7D000-000000006EE7CFFF 0000000000001000 000000000000000F
  24. BS_Data 000000006EE7D000-00000000709FBFFF 0000000000001B7F 000000000000000F
  25. Available 00000000709FC000-00000000710E3FFF 00000000000006E8 000000000000000F
  26. FS1:\> FreePages 0000000020000000 5
  27. FreePages: __PhysAddr__ __PgCnt__
  28. __PhysAddr__ 0... 3FFFFFFFFFFF
  29. __PgCnt__ [0..F000000]
  30. All numbers hex w/ no leading 0x
  31. FreePages(20000000,5)
  32. FS1:\> memmap
  33. Type Start End #pages Attributes
  34. BS_Code 0000000000000000-0000000000000FFF 0000000000000001 000000000000000F
  35. Available 0000000000001000-000000000008DFFF 000000000000008D 000000000000000F
  36. Reserved 000000000008E000-000000000008FFFF 0000000000000002 000000000000000F
  37. Available 0000000000090000-000000000009FFFF 0000000000000010 000000000000000F
  38. Available 0000000000100000-000000000FFFFFFF 000000000000FF00 000000000000000F
  39. BS_Code 0000000010000000-0000000010061FFF 0000000000000062 000000000000000F
  40. Available 0000000010062000-000000005DDFFFFF 000000000004DD9E 000000000000000F
  41. BS_Data 000000005DE00000-000000005DFFFFFF 0000000000000200 000000000000000F
  42. Available 000000005E000000-000000006DE7CFFF 000000000000FE7D 000000000000000F
  43. ACPI_NVS 000000006DE7D000-000000006EE7CFFF 0000000000001000 000000000000000F
  44. BS_Data 000000006EE7D000-00000000709FBFFF 0000000000001B7F 000000000000000F
  45. Available 00000000709FC000-00000000710E3FFF 00000000000006E8 000000000000000F
  46. */
  47. #include <efi.h>
  48. #include <efilib.h>
  49. /*
  50. * FreePages: __PhysAddr__ __PgCnt__
  51. *
  52. */
  53. #define MAX_NUM_PAGES 0x000000000F000000
  54. #define MAX_ADDR ((1ULL << 46) - 1)
  55. #define MAX_ARGS 256
  56. #define CHAR_SPACE L' '
  57. #define DEBUG 0
  58. INTN
  59. argify(CHAR16 *buf, UINTN len, CHAR16 **argv)
  60. {
  61. UINTN i=0, j=0;
  62. CHAR16 *p = buf;
  63. if (buf == 0) {
  64. argv[0] = NULL;
  65. return 0;
  66. }
  67. /* len represents the number of bytes, not the number of 16 bytes chars */
  68. len = len >> 1;
  69. /*
  70. * Here we use CHAR_NULL as the terminator rather than the length
  71. * because it seems like the EFI shell return rather bogus values for it.
  72. * Apparently, we are guaranteed to find the '\0' character in the buffer
  73. * where the real input arguments stop, so we use it instead.
  74. */
  75. for(;;) {
  76. while (buf[i] == CHAR_SPACE && buf[i] != CHAR_NULL && i < len) i++;
  77. if (buf[i] == CHAR_NULL || i == len) goto end;
  78. p = buf+i;
  79. i++;
  80. while (buf[i] != CHAR_SPACE && buf[i] != CHAR_NULL && i < len) i++;
  81. argv[j++] = p;
  82. if (buf[i] == CHAR_NULL) goto end;
  83. buf[i] = CHAR_NULL;
  84. if (i == len) goto end;
  85. i++;
  86. if (j == MAX_ARGS-1) {
  87. Print(L"too many arguments (%d) truncating\n", j);
  88. goto end;
  89. }
  90. }
  91. end:
  92. argv[j] = NULL;
  93. return j;
  94. }
  95. EFI_STATUS
  96. efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
  97. {
  98. EFI_STATUS efi_status;
  99. EFI_GUID LoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
  100. EFI_LOADED_IMAGE *info;
  101. CHAR16 arglist[MAX_ARGS+1] = {0};
  102. CHAR16 *argv[MAX_ARGS];
  103. INTN argc = 0;
  104. INTN err = 0;
  105. INTN PgCnt = -1;
  106. UINTN PhysAddr = 0;
  107. InitializeLib(image, systab);
  108. efi_status = uefi_call_wrapper( BS->HandleProtocol, 3, image,
  109. &LoadedImageProtocol, &info);
  110. Print(L"FreePages: __PhysAddr__ __PgCnt__\n");
  111. Print(L"__PhysAddr__ 0... %llx\n", MAX_ADDR);
  112. Print(L"__PgCnt__ [0..%lx]\n", MAX_NUM_PAGES);
  113. Print(L"All numbers hex w/ no leading 0x\n");
  114. Print(L"\n");
  115. #if DEBUG
  116. Print(L"%s\n", info->LoadOptions);
  117. #endif
  118. #if DEBUG
  119. Print(L"Set up arglist\n");
  120. #endif
  121. CopyMem(arglist, info->LoadOptions, info->LoadOptionsSize);
  122. #if DEBUG
  123. Print(L"arglist = <%s>\n", arglist);
  124. #endif
  125. #if DEBUG
  126. Print(L"Now try argify\n");
  127. #endif
  128. argc = argify(arglist, info->LoadOptionsSize, argv);
  129. #if DEBUG
  130. Print(L"argc = %d\n", argc);
  131. #endif
  132. #if DEBUG
  133. for (c = 0; c < argc; c++ ) {
  134. Print(L"argv[%d] = <%s>\n", c, argv[c]);
  135. }
  136. #endif
  137. if (argc != 3) {
  138. Print(L"Invalid argument count\n");
  139. return EFI_SUCCESS;
  140. }
  141. PhysAddr = xtoi(argv[1]);
  142. PgCnt = xtoi(argv[2]);
  143. if ( (PgCnt < 0) || (PgCnt > MAX_NUM_PAGES) ) {
  144. Print(L"Inavlid PgCnt\n");
  145. err++;
  146. }
  147. if ( PhysAddr > MAX_ADDR ) {
  148. Print(L"Inavlid Address\n");
  149. err++;
  150. }
  151. if ( err ) {
  152. return EFI_SUCCESS;
  153. }
  154. Print(L"FreePages(%lx,%d)\n", PhysAddr, PgCnt);
  155. efi_status = uefi_call_wrapper(BS->FreePages, 2, PhysAddr, PgCnt);
  156. if ( EFI_ERROR(efi_status) ) {
  157. Print(L"Free Pages Failed: %d\n", efi_status);
  158. return efi_status;
  159. }
  160. return EFI_SUCCESS;
  161. }