Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

555 lines
16 KiB

  1. /*++
  2. Copyright (c) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. efidrvent.c
  5. Abstract:
  6. Contains the EFI driver entry abstraction implementation.
  7. Author:
  8. Mandar Gokhale (MandarG@microsoft.com) 14-June-2002
  9. Revision History:
  10. None.
  11. --*/
  12. #include <efidrvent.h>
  13. #include <ntosp.h>
  14. #include <efi.h>
  15. #include <stdio.h>
  16. static
  17. NTSTATUS
  18. EFIDEAddOrUpdateDriverEntry(
  19. IN PDRIVER_ENTRY This,
  20. IN BOOLEAN IsUpdate
  21. )
  22. /*++
  23. Description:
  24. Modify or update a driver entry.
  25. Arguments:
  26. This - Driver entry .
  27. IsUpdate - whether this is a driver entry update or add.
  28. Return Value:
  29. NTSTATUS or add/modify driver operation.
  30. --*/
  31. {
  32. //
  33. // Add this as new boot entry
  34. //
  35. ULONG FullPathLength = 0;
  36. ULONG DevicePathLength = 0;
  37. ULONG SrcPathLength = 0;
  38. ULONG FriendlyNameOffset = 0;
  39. ULONG FriendlyNameLength = 0;
  40. ULONG FilePathLength = 0;
  41. ULONG EntryLength = 0;
  42. ULONG DriverEntryLength = 0;
  43. PEFI_DRIVER_ENTRY DriverEntry = NULL;
  44. PFILE_PATH FilePath;
  45. NTSTATUS Status;
  46. DevicePathLength = (wcslen((PCWSTR)This->NtDevicePath)+ 1) * sizeof(WCHAR);
  47. SrcPathLength = (wcslen((PCWSTR)This->DirPath) + 1) * sizeof(WCHAR);
  48. FullPathLength = DevicePathLength + SrcPathLength;
  49. FriendlyNameOffset = ALIGN_UP(sizeof(EFI_DRIVER_ENTRY), WCHAR);
  50. FriendlyNameLength = (wcslen(This->FriendlyName) + 1) * sizeof(WCHAR);
  51. FilePathLength = FIELD_OFFSET(FILE_PATH, FilePath) + FullPathLength;
  52. EntryLength = FriendlyNameOffset + ALIGN_UP(FriendlyNameLength, ULONG) + FilePathLength;
  53. DriverEntry = SBE_MALLOC(EntryLength);
  54. DriverEntry->Version = EFI_DRIVER_ENTRY_VERSION;
  55. DriverEntry->Length = EntryLength;
  56. DriverEntry->FriendlyNameOffset = FriendlyNameOffset;
  57. DriverEntry->DriverFilePathOffset = FriendlyNameOffset +
  58. ALIGN_UP(FriendlyNameLength, ULONG);
  59. RtlCopyMemory((PCHAR) DriverEntry + DriverEntry->FriendlyNameOffset,
  60. This->FriendlyName,
  61. FriendlyNameLength);
  62. FilePath = (PFILE_PATH) ((PCHAR) DriverEntry + DriverEntry->DriverFilePathOffset);
  63. FilePath->Version = FILE_PATH_VERSION;
  64. FilePath->Length = FilePathLength;
  65. FilePath->Type = FILE_PATH_TYPE_NT;
  66. RtlCopyMemory(FilePath->FilePath, This->NtDevicePath, DevicePathLength );
  67. RtlCopyMemory(FilePath->FilePath + DevicePathLength, This->DirPath, SrcPathLength);
  68. if (IsUpdate){
  69. //
  70. // Update the driver.
  71. //
  72. DriverEntry->Id = This->Id;
  73. Status = NtModifyDriverEntry(DriverEntry);
  74. } else {
  75. //
  76. // Add a new driver entry.
  77. //
  78. Status = NtAddDriverEntry(DriverEntry, &(This->Id));
  79. }
  80. //
  81. // Free allocated memory.
  82. //
  83. if(DriverEntry){
  84. SBE_FREE(DriverEntry);
  85. }
  86. return Status;
  87. }
  88. static
  89. BOOLEAN
  90. EFIDEFlushDriverEntry(
  91. IN PDRIVER_ENTRY This // Points to the driver List.
  92. )
  93. {
  94. BOOLEAN Result = FALSE;
  95. if (This) {
  96. NTSTATUS Status = STATUS_SUCCESS;
  97. if (DRIVERENT_IS_DIRTY(This)) {
  98. if (DRIVERENT_IS_DELETED(This)) {
  99. //
  100. // Delete this entry
  101. //
  102. Status = NtDeleteDriverEntry(This->Id);
  103. } else if (DRIVERENT_IS_NEW(This)) {
  104. //
  105. // Add new Entry.
  106. //
  107. Status = EFIDEAddOrUpdateDriverEntry(This, FALSE);
  108. } else {
  109. //
  110. // Just update this boot entry
  111. //
  112. Status = EFIDEAddOrUpdateDriverEntry(This, TRUE);
  113. }
  114. if (NT_SUCCESS(Status)) {
  115. DRIVERENT_RESET_DIRTY(This);
  116. Result = TRUE;
  117. }
  118. } else {
  119. Result = TRUE; // nothing to flush
  120. }
  121. }
  122. return Result;
  123. }
  124. __inline
  125. BOOLEAN
  126. EFIDEDriverMatch(
  127. IN PDRIVER_ENTRY DriverEntry ,
  128. IN PCWSTR SrcNtFullPath
  129. )
  130. {
  131. BOOLEAN Result = FALSE;
  132. if (!_wcsicmp(DriverEntry->FileName, (wcsrchr(SrcNtFullPath,L'\\')+1))){
  133. Result = TRUE;
  134. }
  135. return(Result);
  136. }
  137. static
  138. PDRIVER_ENTRY
  139. EFIDESearchForDriverEntry(
  140. IN POS_BOOT_OPTIONS This,
  141. IN PCWSTR SrcNtFullPath
  142. )
  143. /*++
  144. Description:
  145. Searches our internal list of driver entries for a match.
  146. It looks up the driver name (not including the path)
  147. for a match. so a\b\c\driver.sys and e\f\driver.sys would be a match.
  148. --*/
  149. {
  150. PDRIVER_ENTRY CurrentDriverEntry = NULL;
  151. if (This && SrcNtFullPath){
  152. CurrentDriverEntry = This->DriverEntries;
  153. while (CurrentDriverEntry){
  154. if (EFIDEDriverMatch(CurrentDriverEntry,
  155. SrcNtFullPath)){
  156. break;
  157. }
  158. CurrentDriverEntry = OSBOGetNextDriverEntry(This, CurrentDriverEntry);
  159. }
  160. }
  161. return (CurrentDriverEntry);
  162. }
  163. PDRIVER_ENTRY
  164. EFIDECreateNewDriverEntry(
  165. IN POS_BOOT_OPTIONS This,
  166. IN PCWSTR FriendlyName,
  167. IN PCWSTR NtDevicePath,
  168. IN PCWSTR DirPath
  169. )
  170. {
  171. PDRIVER_ENTRY DriverEntry = NULL;
  172. if (This && FriendlyName && DirPath && NtDevicePath){
  173. PDRIVER_ENTRY CurrentDriverEntry = NULL;
  174. DriverEntry = (PDRIVER_ENTRY)SBE_MALLOC(sizeof(DRIVER_ENTRY));
  175. memset(DriverEntry, 0, sizeof(DRIVER_ENTRY));
  176. EFIDEDriverEntryInit(DriverEntry);
  177. DriverEntry->BootOptions = This;
  178. //
  179. // Set information for the driver entry.
  180. //
  181. OSDriverSetFileName(DriverEntry, DirPath);
  182. OSDriverSetNtPath(DriverEntry, NtDevicePath);
  183. OSDriverSetDirPath(DriverEntry, DirPath);
  184. OSDriverSetFriendlyName(DriverEntry, FriendlyName);
  185. //
  186. // Mark the driver entry new and dirty.
  187. //
  188. DRIVERENT_SET_NEW(DriverEntry);
  189. DRIVERENT_SET_DIRTY(DriverEntry);
  190. }
  191. return (DriverEntry);
  192. }
  193. PDRIVER_ENTRY
  194. EFIOSBOInsertDriverListNewEntry(
  195. IN POS_BOOT_OPTIONS This,
  196. IN PDRIVER_ENTRY DriverEntry
  197. )
  198. {
  199. if (This && DriverEntry){
  200. PDRIVER_ENTRY CurrentDriverEntry = NULL;
  201. //
  202. // Insert into the list.
  203. //
  204. if (NULL == This->DriverEntries){
  205. //
  206. // No driver entries, this is the first one.
  207. //
  208. This->DriverEntries = DriverEntry;
  209. }else{
  210. //
  211. // Insert in the existing list.
  212. //
  213. DriverEntry->NextEntry = This->DriverEntries;
  214. This->DriverEntries = DriverEntry;
  215. }
  216. }
  217. return (DriverEntry);
  218. }
  219. PDRIVER_ENTRY
  220. EFIDEAddNewDriverEntry(
  221. IN POS_BOOT_OPTIONS This,
  222. IN PCWSTR FriendlyName,
  223. IN PCWSTR NtDevicePath,
  224. IN PCWSTR SrcNtFullPath
  225. )
  226. /*++
  227. Description:
  228. Used to add a new driver entry in NVRAM.
  229. --*/
  230. {
  231. PEFI_DRIVER_ENTRY_LIST DriverList = NULL; // list of driver entries
  232. PDRIVER_ENTRY DriverEntry = NULL;
  233. if (This && FriendlyName && SrcNtFullPath && NtDevicePath){
  234. DriverEntry = EFIDECreateNewDriverEntry(This,
  235. FriendlyName,
  236. NtDevicePath,
  237. SrcNtFullPath);
  238. //
  239. // Mark it as new
  240. //
  241. DRIVERENT_IS_NEW(DriverEntry);
  242. //
  243. // flush the entry,
  244. // see status, if successful put it in the list (only if new)
  245. // otherwise free it
  246. //
  247. if (!OSDriverEntryFlush(DriverEntry)){
  248. SBE_FREE(DriverEntry);
  249. DriverEntry = NULL;
  250. } else {
  251. ULONG OrderCount;
  252. PULONG NewOrder;
  253. //
  254. // If the driver was newly added one then insert it in the driver list.
  255. //
  256. if (DRIVERENT_IS_NEW(DriverEntry)){
  257. EFIOSBOInsertDriverListNewEntry(This,
  258. DriverEntry);
  259. //
  260. // Increment the count of the number of driver entries in the list.
  261. //
  262. This->DriverEntryCount++;
  263. //
  264. // Put the new entry at the end of the boot order
  265. //
  266. OrderCount = OSBOGetOrderedDriverEntryCount(This);
  267. NewOrder = (PULONG)SBE_MALLOC((OrderCount + 1) * sizeof(ULONG));
  268. if (NewOrder) {
  269. memset(NewOrder, 0, sizeof(ULONG) * (OrderCount + 1));
  270. //
  271. // copy over the old ordered list
  272. //
  273. memcpy(NewOrder, This->DriverEntryOrder, sizeof(ULONG) * OrderCount);
  274. NewOrder[OrderCount] = OSDriverGetId((PDRIVER_ENTRY)DriverEntry);
  275. SBE_FREE(This->DriverEntryOrder);
  276. This->DriverEntryOrder = NewOrder;
  277. This->DriverEntryOrderCount = OrderCount + 1;
  278. } else {
  279. //
  280. // Remove the driver entry out of the link list.
  281. // Just freeing it will cause memory leaks.
  282. // TBD: decide if we want to delete this driver entry too
  283. //
  284. This->DriverEntries = DriverEntry->NextEntry;
  285. SBE_FREE(DriverEntry);
  286. DriverEntry = NULL;
  287. }
  288. }
  289. }
  290. }
  291. return DriverEntry;
  292. }
  293. __inline
  294. ULONG
  295. EFIDESetDriverId(
  296. IN PDRIVER_ENTRY This,
  297. IN ULONG DriverId
  298. )
  299. {
  300. if (This){
  301. This->Id = DriverId;
  302. }
  303. return (DriverId);
  304. }
  305. PDRIVER_ENTRY
  306. EFIDECreateDriverEntry(PEFI_DRIVER_ENTRY_LIST Entry,
  307. POS_BOOT_OPTIONS This )
  308. /*++
  309. Description:
  310. Used to interpret a driver entry returned by NtEnumerateDriverEntries(..)
  311. into our format.
  312. Arguments:
  313. Entry - EFI format driver entry returned to us by NT.
  314. This - container for the driver entry list that we generate.
  315. Return:
  316. PDRIVER_ENTRY ( driver entry in our format).
  317. --*/
  318. {
  319. PDRIVER_ENTRY ResultDriverEntry = NULL;
  320. if (Entry && This){
  321. PFILE_PATH FilePath = (PFILE_PATH) ((PCHAR) &Entry->DriverEntry +
  322. Entry->DriverEntry.DriverFilePathOffset);
  323. PWCHAR FriendlyName = (PWCHAR)((PCHAR)&Entry->DriverEntry +
  324. Entry->DriverEntry.FriendlyNameOffset);
  325. ULONG NtDevicePathLength = 0;
  326. PDRIVER_ENTRY DriverEntry = NULL;
  327. PFILE_PATH DriverOptionPath = NULL;
  328. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  329. if(FilePath->Type != FILE_PATH_TYPE_NT) {
  330. PVOID Buffer;
  331. ULONG PathLength = 0;
  332. Status = NtTranslateFilePath(FilePath, FILE_PATH_TYPE_NT, NULL, &PathLength);
  333. if(NT_SUCCESS(Status)) {
  334. Status = STATUS_UNSUCCESSFUL;
  335. }
  336. if(STATUS_BUFFER_TOO_SMALL == Status) {
  337. ASSERT(PathLength != 0);
  338. DriverOptionPath = (PFILE_PATH)SBE_MALLOC(PathLength);
  339. memset(DriverOptionPath, 0, sizeof(PathLength));
  340. Status = NtTranslateFilePath(FilePath,
  341. FILE_PATH_TYPE_NT,
  342. DriverOptionPath,
  343. &PathLength);
  344. }
  345. if(!NT_SUCCESS(Status)) {
  346. if(STATUS_OBJECT_PATH_NOT_FOUND == Status || STATUS_OBJECT_NAME_NOT_FOUND == Status) {
  347. //
  348. // This entry is stale; remove it
  349. //
  350. NtDeleteDriverEntry(Entry->DriverEntry.Id);
  351. }
  352. //
  353. // Free the DriverOptionPath memory
  354. //
  355. if(DriverOptionPath != NULL) {
  356. SBE_FREE(DriverOptionPath);
  357. DriverOptionPath = NULL;
  358. }
  359. }
  360. }
  361. if (DriverOptionPath){
  362. ULONG FilePathLength = 0;
  363. DriverEntry = (PDRIVER_ENTRY)SBE_MALLOC(sizeof(DRIVER_ENTRY));
  364. memset(DriverEntry, 0, sizeof(DRIVER_ENTRY));
  365. //
  366. // Set pointer back to boot options (container).
  367. //
  368. DriverEntry->BootOptions = This;
  369. EFIDEDriverEntryInit(DriverEntry);
  370. //
  371. // Set driver ID.
  372. //
  373. EFIDESetDriverId(DriverEntry, Entry->DriverEntry.Id);
  374. //
  375. // Set File Name.
  376. //
  377. NtDevicePathLength = wcslen((PCWSTR) DriverOptionPath->FilePath) + 1;
  378. OSDriverSetFileName(DriverEntry,
  379. (PCWSTR) DriverOptionPath->FilePath + NtDevicePathLength);
  380. //
  381. // Set NT path and Driver dir.
  382. //
  383. OSDriverSetNtPath(DriverEntry, (PCWSTR)DriverOptionPath->FilePath);
  384. OSDriverSetDirPath(DriverEntry, (PCWSTR)(DriverOptionPath->FilePath) + NtDevicePathLength);
  385. //
  386. // Set Friendly Name.
  387. //
  388. OSDriverSetFriendlyName(DriverEntry, FriendlyName);
  389. //
  390. // Free the DriverOptionPath memory
  391. //
  392. if(DriverOptionPath != NULL) {
  393. SBE_FREE(DriverOptionPath);
  394. }
  395. ResultDriverEntry = DriverEntry;
  396. }
  397. }
  398. return ResultDriverEntry;
  399. }
  400. NTSTATUS
  401. EFIDEInterpretDriverEntries(
  402. IN POS_BOOT_OPTIONS This,
  403. IN PEFI_DRIVER_ENTRY_LIST DriverList
  404. )
  405. /*++
  406. Description:
  407. Used to interpret the driver entries returned by NtEnumerateDriverEntries(..)
  408. into our format.
  409. Arguments:
  410. This - container for the driver entry list that we generate.
  411. DriverList - Driver list returned by NtEnumerateDriverEntries(..).
  412. Return:
  413. NTSTATUS code.
  414. --*/
  415. {
  416. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  417. if (This && DriverList){
  418. PEFI_DRIVER_ENTRY_LIST Entry;
  419. PDRIVER_ENTRY DriverEntry = NULL;
  420. BOOLEAN Continue = TRUE;
  421. Status = STATUS_SUCCESS;
  422. for(Entry = DriverList;
  423. Continue;
  424. Entry = (PEFI_DRIVER_ENTRY_LIST) ((PCHAR) Entry +
  425. Entry->NextEntryOffset)) {
  426. Continue = (Entry->NextEntryOffset != 0);
  427. DriverEntry = EFIDECreateDriverEntry(Entry, This);
  428. if (DriverEntry){
  429. //
  430. // Insert into the list of drivers in the OSBO structure.
  431. //
  432. if (NULL == This->DriverEntries){
  433. This->DriverEntries = DriverEntry;
  434. } else{
  435. DriverEntry->NextEntry = This->DriverEntries;
  436. This->DriverEntries = DriverEntry;
  437. }
  438. This->DriverEntryCount++;
  439. }
  440. }
  441. }
  442. return Status;
  443. }
  444. static
  445. VOID
  446. EFIDEDriverEntryInit(
  447. IN PDRIVER_ENTRY This
  448. )
  449. {
  450. This->Flush = EFIDEFlushDriverEntry;
  451. }