misc.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. misc.c
  9. Abstract:
  10. This module implements miscellaneous OS support functions for the setup
  11. application.
  12. Author:
  13. Evan Green 16-Apr-2014
  14. Environment:
  15. User
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <assert.h>
  21. #include <errno.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include "../setup.h"
  25. #include <minoca/lib/mlibc.h>
  26. #include <minoca/fw/smbios.h>
  27. //
  28. // ---------------------------------------------------------------- Definitions
  29. //
  30. #define SMBIOS_DEFAULT_ALLOCATION_SIZE 0x1000
  31. //
  32. // ------------------------------------------------------ Data Type Definitions
  33. //
  34. //
  35. // ----------------------------------------------- Internal Function Prototypes
  36. //
  37. PSTR
  38. SetupOsGetSmbiosString (
  39. PSMBIOS_HEADER Header,
  40. ULONG StringNumber
  41. );
  42. //
  43. // -------------------------------------------------------------------- Globals
  44. //
  45. //
  46. // ------------------------------------------------------------------ Functions
  47. //
  48. INT
  49. SetupOsReboot (
  50. VOID
  51. )
  52. /*++
  53. Routine Description:
  54. This routine reboots the machine.
  55. Arguments:
  56. None.
  57. Return Value:
  58. 0 on success.
  59. Non-zero on failure.
  60. --*/
  61. {
  62. KSTATUS Status;
  63. fflush(NULL);
  64. Status = OsResetSystem(SystemResetWarm);
  65. if (!KSUCCESS(Status)) {
  66. return ClConvertKstatusToErrorNumber(Status);
  67. }
  68. return 0;
  69. }
  70. INT
  71. SetupOsGetPlatformName (
  72. PSTR *Name,
  73. PSETUP_RECIPE_ID Fallback
  74. )
  75. /*++
  76. Routine Description:
  77. This routine gets the platform name.
  78. Arguments:
  79. Name - Supplies a pointer where a pointer to an allocated string containing
  80. the SMBIOS system information product name will be returned if
  81. available. The caller is responsible for freeing this memory when done.
  82. Fallback - Supplies a fallback platform to use if the given platform
  83. string was not returned or did not match a known platform.
  84. Return Value:
  85. 0 on success.
  86. Non-zero on failure.
  87. --*/
  88. {
  89. PSTR CurrentString;
  90. PVOID End;
  91. ULONG FirmwareType;
  92. PSTR PlatformName;
  93. UINTN Size;
  94. PSMBIOS_ENTRY_POINT SmbiosEntryPoint;
  95. PSTR SmbiosProductName;
  96. KSTATUS Status;
  97. PSMBIOS_SYSTEM_INFORMATION SystemInformation;
  98. PlatformName = NULL;
  99. SmbiosEntryPoint = NULL;
  100. //
  101. // First figure out the fallback based on the firmware type.
  102. //
  103. if (Fallback != NULL) {
  104. Size = sizeof(FirmwareType);
  105. Status = OsGetSetSystemInformation(SystemInformationKe,
  106. KeInformationFirmwareType,
  107. &FirmwareType,
  108. &Size,
  109. FALSE);
  110. if (!KSUCCESS(Status)) {
  111. goto OsGetPlatformNameEnd;
  112. }
  113. if (FirmwareType == SystemFirmwareEfi) {
  114. if (sizeof(PVOID) == 8) {
  115. *Fallback = SetupRecipePc64Efi;
  116. } else {
  117. *Fallback = SetupRecipePc32Efi;
  118. }
  119. } else if (FirmwareType == SystemFirmwarePcat) {
  120. if (sizeof(PVOID) == 8) {
  121. *Fallback = SetupRecipePc64;
  122. } else {
  123. *Fallback = SetupRecipePc32;
  124. }
  125. } else {
  126. *Fallback = SetupRecipeNone;
  127. }
  128. }
  129. //
  130. // Get the SMBIOS tables.
  131. //
  132. Size = SMBIOS_DEFAULT_ALLOCATION_SIZE;
  133. SmbiosEntryPoint = malloc(Size);
  134. if (SmbiosEntryPoint == NULL) {
  135. Status = STATUS_INSUFFICIENT_RESOURCES;
  136. goto OsGetPlatformNameEnd;
  137. }
  138. SmbiosEntryPoint->AnchorString = SMBIOS_ANCHOR_STRING_VALUE;
  139. Status = OsGetSetSystemInformation(SystemInformationKe,
  140. KeInformationFirmwareTable,
  141. SmbiosEntryPoint,
  142. &Size,
  143. FALSE);
  144. if (!KSUCCESS(Status)) {
  145. if (Status == STATUS_NOT_FOUND) {
  146. Status = STATUS_SUCCESS;
  147. goto OsGetPlatformNameEnd;
  148. }
  149. if (Status == STATUS_BUFFER_TOO_SMALL) {
  150. free(SmbiosEntryPoint);
  151. SmbiosEntryPoint = malloc(Size);
  152. if (SmbiosEntryPoint == NULL) {
  153. Status = STATUS_INSUFFICIENT_RESOURCES;
  154. goto OsGetPlatformNameEnd;
  155. }
  156. SmbiosEntryPoint->AnchorString = SMBIOS_ANCHOR_STRING_VALUE;
  157. Status = OsGetSetSystemInformation(SystemInformationKe,
  158. KeInformationFirmwareTable,
  159. SmbiosEntryPoint,
  160. &Size,
  161. FALSE);
  162. if (!KSUCCESS(Status)) {
  163. goto OsGetPlatformNameEnd;
  164. }
  165. }
  166. goto OsGetPlatformNameEnd;
  167. }
  168. //
  169. // Search the SMBIOS tables for the system information structure.
  170. //
  171. SystemInformation = (PSMBIOS_SYSTEM_INFORMATION)(SmbiosEntryPoint + 1);
  172. End = (PVOID)SystemInformation + SmbiosEntryPoint->StructureTableLength;
  173. while ((PVOID)SystemInformation < End) {
  174. //
  175. // If this is not the right structure, advance past the structure and
  176. // all the strings.
  177. //
  178. if (SystemInformation->Header.Type != SmbiosSystemInformation) {
  179. CurrentString = ((PVOID)SystemInformation) +
  180. SystemInformation->Header.Length;
  181. while (((PVOID)CurrentString < End) &&
  182. ((*CurrentString != '\0') ||
  183. (*(CurrentString + 1) != '\0'))) {
  184. CurrentString += 1;
  185. }
  186. SystemInformation = (PSMBIOS_SYSTEM_INFORMATION)(CurrentString + 2);
  187. continue;
  188. }
  189. break;
  190. }
  191. if ((PVOID)SystemInformation >= End) {
  192. Status = STATUS_SUCCESS;
  193. goto OsGetPlatformNameEnd;
  194. }
  195. //
  196. // Get the product name string.
  197. //
  198. SmbiosProductName = SetupOsGetSmbiosString(&(SystemInformation->Header),
  199. SystemInformation->ProductName);
  200. if (SmbiosProductName == NULL) {
  201. Status = STATUS_SUCCESS;
  202. goto OsGetPlatformNameEnd;
  203. }
  204. PlatformName = strdup(SmbiosProductName);
  205. if (PlatformName == NULL) {
  206. Status = STATUS_INSUFFICIENT_RESOURCES;
  207. goto OsGetPlatformNameEnd;
  208. }
  209. Status = STATUS_SUCCESS;
  210. OsGetPlatformNameEnd:
  211. if (SmbiosEntryPoint != NULL) {
  212. free(SmbiosEntryPoint);
  213. }
  214. if (!KSUCCESS(Status)) {
  215. if (PlatformName != NULL) {
  216. free(PlatformName);
  217. PlatformName = NULL;
  218. }
  219. }
  220. *Name = PlatformName;
  221. return ClConvertKstatusToErrorNumber(Status);
  222. }
  223. INT
  224. SetupOsGetSystemMemorySize (
  225. PULONGLONG Megabytes
  226. )
  227. /*++
  228. Routine Description:
  229. This routine returns the number of megabytes of memory installed on the
  230. currently running system.
  231. Arguments:
  232. Megabytes - Supplies a pointer to where the system memory capacity in
  233. megabytes will be returned on success.
  234. Return Value:
  235. 0 on success.
  236. Non-zero on failure.
  237. --*/
  238. {
  239. ULONGLONG MemoryBytes;
  240. MM_STATISTICS Statistics;
  241. UINTN StatisticsSize;
  242. KSTATUS Status;
  243. Statistics.Version = MM_STATISTICS_VERSION;
  244. StatisticsSize = sizeof(MM_STATISTICS);
  245. Status = OsGetSetSystemInformation(SystemInformationMm,
  246. MmInformationSystemMemory,
  247. &Statistics,
  248. &StatisticsSize,
  249. FALSE);
  250. if (!KSUCCESS(Status)) {
  251. return ClConvertKstatusToErrorNumber(Status);
  252. }
  253. assert(Statistics.PageSize != 0);
  254. MemoryBytes = Statistics.PhysicalPages * Statistics.PageSize;
  255. *Megabytes = ALIGN_RANGE_UP(MemoryBytes, _1MB) / _1MB;
  256. return 0;
  257. }
  258. //
  259. // --------------------------------------------------------- Internal Functions
  260. //
  261. PSTR
  262. SetupOsGetSmbiosString (
  263. PSMBIOS_HEADER Header,
  264. ULONG StringNumber
  265. )
  266. /*++
  267. Routine Description:
  268. This routine gets the desired string from an SMBIOS structure.
  269. Arguments:
  270. Header - Supplies a pointer to the header of the table.
  271. StringNumber - Supplies the one-based string index of the string to get.
  272. Return Value:
  273. NULL if the string number is zero or invalid.
  274. --*/
  275. {
  276. PSTR CurrentString;
  277. ULONG StringIndex;
  278. ULONG StringLength;
  279. if (StringNumber == 0) {
  280. return NULL;
  281. }
  282. CurrentString = ((PVOID)Header) + Header->Length;
  283. for (StringIndex = 0; StringIndex < StringNumber - 1; StringIndex += 1) {
  284. StringLength = 0;
  285. while (*CurrentString != '\0') {
  286. CurrentString += 1;
  287. StringLength += 1;
  288. }
  289. //
  290. // If a double null was found, then this string number is invalid.
  291. //
  292. if (StringLength == 0) {
  293. return NULL;
  294. }
  295. CurrentString += 1;
  296. }
  297. return CurrentString;
  298. }