misc.c 8.7 KB

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