dispatch.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. dispatch.c
  5. Abstract:
  6. This module implements the driver dispatcher.
  7. Author:
  8. Evan Green 12-Mar-2014
  9. Environment:
  10. Firmware
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "ueficore.h"
  16. #include "fwvolp.h"
  17. //
  18. // ---------------------------------------------------------------- Definitions
  19. //
  20. #define EFI_CORE_DRIVER_ENTRY_MAGIC 0x76697244 // 'virD'
  21. //
  22. // ------------------------------------------------------ Data Type Definitions
  23. //
  24. typedef struct _EFI_KNOWN_HANDLE {
  25. LIST_ENTRY ListEntry;
  26. EFI_HANDLE Handle;
  27. EFI_GUID NameGuid;
  28. } EFI_KNOWN_HANDLE, *PEFI_KNOWN_HANDLE;
  29. typedef struct _EFI_CORE_DRIVER_ENTRY {
  30. UINTN Magic;
  31. LIST_ENTRY DriverListEntry;
  32. LIST_ENTRY SchedulerListEntry;
  33. EFI_HANDLE VolumeHandle;
  34. EFI_GUID FileName;
  35. EFI_DEVICE_PATH_PROTOCOL *FileDevicePath;
  36. EFI_FIRMWARE_VOLUME2_PROTOCOL *Volume;
  37. EFI_HANDLE ImageHandle;
  38. BOOLEAN IsFirmwareVolumeImage;
  39. BOOLEAN Untrusted;
  40. BOOLEAN Initialized;
  41. BOOLEAN Scheduled;
  42. BOOLEAN Dependent;
  43. } EFI_CORE_DRIVER_ENTRY, *PEFI_CORE_DRIVER_ENTRY;
  44. typedef struct _EFI_FIRMWARE_VOLUME_FILE_DEVICE_PATH {
  45. MEDIA_FW_VOL_FILEPATH_DEVICE_PATH File;
  46. EFI_DEVICE_PATH_PROTOCOL End;
  47. } EFI_FIRMWARE_VOLUME_FILE_DEVICE_PATH, *PEFI_FIRMWARE_VOLUME_FILE_DEVICE_PATH;
  48. //
  49. // ----------------------------------------------- Internal Function Prototypes
  50. //
  51. EFIAPI
  52. VOID
  53. EfipFirmwareVolumeEventProtocolNotify (
  54. EFI_EVENT Event,
  55. VOID *Context
  56. );
  57. BOOLEAN
  58. EfipFirmwareVolumeHasBeenProcessed (
  59. EFI_HANDLE Handle
  60. );
  61. PEFI_KNOWN_HANDLE
  62. EfipMarkFirmwareVolumeProcessed (
  63. EFI_HANDLE Handle
  64. );
  65. EFI_STATUS
  66. EfipCoreAddDriverToList (
  67. EFI_FIRMWARE_VOLUME2_PROTOCOL *Volume,
  68. EFI_HANDLE VolumeHandle,
  69. EFI_GUID *DriverName,
  70. EFI_FV_FILETYPE Type
  71. );
  72. EFI_DEVICE_PATH_PROTOCOL *
  73. EfipCoreConvertFirmwareVolumeFileToDevicePath (
  74. EFI_FIRMWARE_VOLUME2_PROTOCOL *Volume,
  75. EFI_HANDLE VolumeHandle,
  76. EFI_GUID *DriverName
  77. );
  78. VOID
  79. EfipCoreInsertOnScheduledQueue (
  80. PEFI_CORE_DRIVER_ENTRY DriverEntry
  81. );
  82. //
  83. // -------------------------------------------------------------------- Globals
  84. //
  85. //
  86. // Store the list of known firmware volume handles.
  87. //
  88. LIST_ENTRY EfiFirmwareVolumeList;
  89. //
  90. // Define the variables used to register for firmware volume arrivals.
  91. //
  92. EFI_EVENT EfiFirmwareVolumeEvent;
  93. VOID *EfiFirmwareVolumeEventRegistration;
  94. //
  95. // Define the list of file types supported by the dispatcher.
  96. //
  97. EFI_FV_FILETYPE EfiDispatcherFileTypes[] = {
  98. EFI_FV_FILETYPE_DRIVER,
  99. EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,
  100. };
  101. EFI_LOCK EfiDispatcherLock;
  102. LIST_ENTRY EfiDiscoveredList;
  103. LIST_ENTRY EfiScheduledQueue;
  104. BOOLEAN EfiDispatcherRunning;
  105. //
  106. // ------------------------------------------------------------------ Functions
  107. //
  108. VOID
  109. EfiCoreInitializeDispatcher (
  110. VOID
  111. )
  112. /*++
  113. Routine Description:
  114. This routine initializes the driver dispatcher.
  115. Arguments:
  116. None.
  117. Return Value:
  118. None.
  119. --*/
  120. {
  121. INITIALIZE_LIST_HEAD(&EfiFirmwareVolumeList);
  122. INITIALIZE_LIST_HEAD(&EfiDiscoveredList);
  123. INITIALIZE_LIST_HEAD(&EfiScheduledQueue);
  124. EfiCoreInitializeLock(&EfiDispatcherLock, TPL_HIGH_LEVEL);
  125. EfiFirmwareVolumeEvent = EfiCoreCreateProtocolNotifyEvent(
  126. &EfiFirmwareVolume2ProtocolGuid,
  127. TPL_CALLBACK,
  128. EfipFirmwareVolumeEventProtocolNotify,
  129. NULL,
  130. &EfiFirmwareVolumeEventRegistration);
  131. ASSERT(EfiFirmwareVolumeEvent != NULL);
  132. return;
  133. }
  134. EFIAPI
  135. EFI_STATUS
  136. EfiCoreDispatcher (
  137. VOID
  138. )
  139. /*++
  140. Routine Description:
  141. This routine runs the driver dispatcher. It drains the scheduled queue
  142. loading and starting drivers until there are no more drivers to run.
  143. Arguments:
  144. None.
  145. Return Value:
  146. EFI_SUCCESS if one or more drivers were loaded.
  147. EFI_NOT_FOUND if no drivers were loaded.
  148. EFI_ALREADY_STARTED if the dispatcher is already running.
  149. --*/
  150. {
  151. PLIST_ENTRY CurrentEntry;
  152. PEFI_CORE_DRIVER_ENTRY DriverEntry;
  153. BOOLEAN ReadyToRun;
  154. EFI_STATUS ReturnStatus;
  155. EFI_STATUS Status;
  156. if (EfiDispatcherRunning != FALSE) {
  157. return EFI_ALREADY_STARTED;
  158. }
  159. EfiDispatcherRunning = TRUE;
  160. ReturnStatus = EFI_NOT_FOUND;
  161. do {
  162. //
  163. // Drain the scheduled queue.
  164. //
  165. while (LIST_EMPTY(&EfiScheduledQueue) == FALSE) {
  166. DriverEntry = LIST_VALUE(EfiScheduledQueue.Next,
  167. EFI_CORE_DRIVER_ENTRY,
  168. SchedulerListEntry);
  169. ASSERT(DriverEntry->Magic == EFI_CORE_DRIVER_ENTRY_MAGIC);
  170. //
  171. // Load the driver into memory if needed.
  172. //
  173. if ((DriverEntry->ImageHandle == NULL) &&
  174. (DriverEntry->IsFirmwareVolumeImage == FALSE)) {
  175. Status = EfiCoreLoadImage(FALSE,
  176. EfiFirmwareImageHandle,
  177. DriverEntry->FileDevicePath,
  178. NULL,
  179. 0,
  180. &(DriverEntry->ImageHandle));
  181. if (EFI_ERROR(Status)) {
  182. RtlDebugPrint("Warning: Driver failed load with status "
  183. "0x%x.\n",
  184. Status);
  185. EfiCoreAcquireLock(&EfiDispatcherLock);
  186. if (Status == EFI_SECURITY_VIOLATION) {
  187. DriverEntry->Untrusted = TRUE;
  188. } else {
  189. DriverEntry->Initialized = TRUE;
  190. }
  191. DriverEntry->Scheduled = FALSE;
  192. LIST_REMOVE(&(DriverEntry->SchedulerListEntry));
  193. EfiCoreReleaseLock(&EfiDispatcherLock);
  194. //
  195. // Don't try to start this image, it failed to load.
  196. //
  197. continue;
  198. }
  199. }
  200. EfiCoreAcquireLock(&EfiDispatcherLock);
  201. DriverEntry->Scheduled = FALSE;
  202. DriverEntry->Initialized = TRUE;
  203. LIST_REMOVE(&(DriverEntry->SchedulerListEntry));
  204. EfiCoreReleaseLock(&EfiDispatcherLock);
  205. if (DriverEntry->IsFirmwareVolumeImage == FALSE) {
  206. ASSERT(DriverEntry->ImageHandle != NULL);
  207. Status = EfiCoreStartImage(DriverEntry->ImageHandle,
  208. NULL,
  209. NULL);
  210. if (EFI_ERROR(Status)) {
  211. RtlDebugPrint("Warning: Driver start failed with "
  212. "status 0x%x.\n",
  213. Status);
  214. }
  215. }
  216. ReturnStatus = EFI_SUCCESS;
  217. }
  218. //
  219. // Search the discovered list for items to place on the scheduled
  220. // queue.
  221. //
  222. ReadyToRun = FALSE;
  223. CurrentEntry = EfiDiscoveredList.Next;
  224. while (CurrentEntry != &EfiDiscoveredList) {
  225. DriverEntry = LIST_VALUE(CurrentEntry,
  226. EFI_CORE_DRIVER_ENTRY,
  227. DriverListEntry);
  228. CurrentEntry = CurrentEntry->Next;
  229. if (DriverEntry->Dependent != FALSE) {
  230. EfipCoreInsertOnScheduledQueue(DriverEntry);
  231. ReadyToRun = TRUE;
  232. }
  233. }
  234. } while (ReadyToRun != FALSE);
  235. EfiDispatcherRunning = FALSE;
  236. return ReturnStatus;
  237. }
  238. //
  239. // --------------------------------------------------------- Internal Functions
  240. //
  241. EFIAPI
  242. VOID
  243. EfipFirmwareVolumeEventProtocolNotify (
  244. EFI_EVENT Event,
  245. VOID *Context
  246. )
  247. /*++
  248. Routine Description:
  249. This routine is called when a new firmware volume protocol appears in the
  250. system.
  251. Arguments:
  252. Event - Supplies a pointer to the event that fired.
  253. Context - Supplies an unused context pointer.
  254. Return Value:
  255. None.
  256. --*/
  257. {
  258. EFI_FV_FILE_ATTRIBUTES Attributes;
  259. UINTN BufferSize;
  260. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  261. UINTN FileTypeCount;
  262. EFI_STATUS GetNextFileStatus;
  263. UINTN Index;
  264. UINTN Key;
  265. PEFI_KNOWN_HANDLE KnownHandle;
  266. EFI_GUID NameGuid;
  267. UINTN Size;
  268. EFI_STATUS Status;
  269. EFI_FV_FILETYPE Type;
  270. EFI_FIRMWARE_VOLUME2_PROTOCOL *Volume;
  271. EFI_HANDLE VolumeHandle;
  272. //
  273. // Loop through all the new firmware volumes.
  274. //
  275. while (TRUE) {
  276. BufferSize = sizeof(EFI_HANDLE);
  277. Status = EfiCoreLocateHandle(ByRegisterNotify,
  278. NULL,
  279. EfiFirmwareVolumeEventRegistration,
  280. &BufferSize,
  281. &VolumeHandle);
  282. if (EFI_ERROR(Status)) {
  283. break;
  284. }
  285. if (EfipFirmwareVolumeHasBeenProcessed(VolumeHandle) != FALSE) {
  286. continue;
  287. }
  288. KnownHandle = EfipMarkFirmwareVolumeProcessed(VolumeHandle);
  289. if (KnownHandle == NULL) {
  290. continue;
  291. }
  292. Status = EfiCoreHandleProtocol(VolumeHandle,
  293. &EfiFirmwareVolume2ProtocolGuid,
  294. (VOID **)&Volume);
  295. if ((EFI_ERROR(Status)) || (Volume == NULL)) {
  296. ASSERT(FALSE);
  297. continue;
  298. }
  299. Status = EfiCoreHandleProtocol(VolumeHandle,
  300. &EfiDevicePathProtocolGuid,
  301. (VOID **)&DevicePath);
  302. if (EFI_ERROR(Status)) {
  303. continue;
  304. }
  305. //
  306. // Discover drivers in the firmware volume and add them to the
  307. // discovered driver list.
  308. //
  309. FileTypeCount = sizeof(EfiDispatcherFileTypes) /
  310. sizeof(EfiDispatcherFileTypes[0]);
  311. for (Index = 0; Index < FileTypeCount; Index += 1) {
  312. Key = 0;
  313. while (TRUE) {
  314. Type = EfiDispatcherFileTypes[Index];
  315. GetNextFileStatus = Volume->GetNextFile(Volume,
  316. &Key,
  317. &Type,
  318. &NameGuid,
  319. &Attributes,
  320. &Size);
  321. if (EFI_ERROR(GetNextFileStatus)) {
  322. break;
  323. }
  324. EfipCoreAddDriverToList(Volume, VolumeHandle, &NameGuid, Type);
  325. }
  326. }
  327. }
  328. return;
  329. }
  330. BOOLEAN
  331. EfipFirmwareVolumeHasBeenProcessed (
  332. EFI_HANDLE Handle
  333. )
  334. /*++
  335. Routine Description:
  336. This routine determines if the given firmware volume has been processed.
  337. Arguments:
  338. Handle - Supplies the handle to the volume.
  339. Return Value:
  340. TRUE if the handle has been processed.
  341. FALSE if the handle has not been processed.
  342. --*/
  343. {
  344. PLIST_ENTRY CurrentEntry;
  345. PEFI_KNOWN_HANDLE KnownHandle;
  346. CurrentEntry = EfiFirmwareVolumeList.Next;
  347. while (CurrentEntry != &EfiFirmwareVolumeList) {
  348. KnownHandle = LIST_VALUE(CurrentEntry, EFI_KNOWN_HANDLE, ListEntry);
  349. if (KnownHandle->Handle == Handle) {
  350. return TRUE;
  351. }
  352. CurrentEntry = CurrentEntry->Next;
  353. }
  354. return FALSE;
  355. }
  356. PEFI_KNOWN_HANDLE
  357. EfipMarkFirmwareVolumeProcessed (
  358. EFI_HANDLE Handle
  359. )
  360. /*++
  361. Routine Description:
  362. This routine marks a firmware volume handle as having been processed. This
  363. function adds entries on the firmware volume list if the new entry is
  364. different from the one in the handle list by checking the firmware volume
  365. image GUID. Items are never removed/free from the firmware volume list.
  366. Arguments:
  367. Handle - Supplies the handle to the volume.
  368. Return Value:
  369. Returns a pointer to the new known handle structure.
  370. NULL if a firmware volume with the same GUID was already processed.
  371. --*/
  372. {
  373. EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BlockIo;
  374. EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
  375. PLIST_ENTRY CurrentEntry;
  376. UINT32 ExtHeaderOffset;
  377. UINTN Index;
  378. PEFI_KNOWN_HANDLE KnownHandle;
  379. EFI_LBA LbaIndex;
  380. UINTN LbaOffset;
  381. EFI_GUID NameGuid;
  382. BOOLEAN NameGuidFound;
  383. EFI_STATUS Status;
  384. EFI_FIRMWARE_VOLUME_HEADER *VolumeHeader;
  385. NameGuidFound = FALSE;
  386. //
  387. // Get the firmware volume block protocol on the handle. Going rogue.
  388. //
  389. Status = EfiCoreHandleProtocol(Handle,
  390. &EfiFirmwareVolumeBlockProtocolGuid,
  391. (VOID **)&BlockIo);
  392. if (!EFI_ERROR(Status)) {
  393. //
  394. // Get the full volume header using the block I/O protocol.
  395. //
  396. ASSERT(BlockIo != NULL);
  397. Status = EfiFvGetVolumeHeader(BlockIo, &VolumeHeader);
  398. if (!EFI_ERROR(Status)) {
  399. ASSERT(VolumeHeader != NULL);
  400. if ((EfiFvVerifyHeaderChecksum(VolumeHeader) != FALSE) &&
  401. (VolumeHeader->ExtHeaderOffset != 0)) {
  402. ExtHeaderOffset = VolumeHeader->ExtHeaderOffset;
  403. BlockMap = VolumeHeader->BlockMap;
  404. LbaIndex = 0;
  405. LbaOffset = 0;
  406. //
  407. // Find the LBA index and offset for the volume extension
  408. // header using the block map.
  409. //
  410. while ((BlockMap->BlockCount != 0) ||
  411. (BlockMap->BlockLength != 0)) {
  412. for (Index = 0;
  413. Index < BlockMap->BlockCount;
  414. Index += 1) {
  415. if (ExtHeaderOffset < BlockMap->BlockLength) {
  416. break;
  417. }
  418. ExtHeaderOffset -= BlockMap->BlockLength;
  419. LbaIndex += 1;
  420. }
  421. if (Index < BlockMap->BlockCount) {
  422. LbaOffset = ExtHeaderOffset;
  423. break;
  424. }
  425. BlockMap += 1;
  426. }
  427. Status = EfiFvReadData(BlockIo,
  428. &LbaIndex,
  429. &LbaOffset,
  430. sizeof(NameGuid),
  431. (UINT8 *)&NameGuid);
  432. if (!EFI_ERROR(Status)) {
  433. NameGuidFound = TRUE;
  434. }
  435. }
  436. EfiCoreFreePool(VolumeHeader);
  437. }
  438. }
  439. //
  440. // If a name GUID for this volume was found, compare it with all the other
  441. // known volumes.
  442. //
  443. if (NameGuidFound != FALSE) {
  444. CurrentEntry = EfiFirmwareVolumeList.Next;
  445. while (CurrentEntry != &EfiFirmwareVolumeList) {
  446. KnownHandle = LIST_VALUE(CurrentEntry, EFI_KNOWN_HANDLE, ListEntry);
  447. if (EfiCoreCompareGuids(&NameGuid, &(KnownHandle->NameGuid)) !=
  448. FALSE) {
  449. RtlDebugPrint("Found two firmware volumes with the same GUID. "
  450. "Skipping one!\n");
  451. return NULL;
  452. }
  453. }
  454. }
  455. KnownHandle = EfiCoreAllocateBootPool(sizeof(EFI_KNOWN_HANDLE));
  456. if (KnownHandle == NULL) {
  457. ASSERT(FALSE);
  458. return NULL;
  459. }
  460. EfiCoreSetMemory(KnownHandle, sizeof(EFI_KNOWN_HANDLE), 0);
  461. KnownHandle->Handle = Handle;
  462. if (NameGuidFound != FALSE) {
  463. EfiCoreCopyMemory(&(KnownHandle->NameGuid),
  464. &NameGuid,
  465. sizeof(EFI_GUID));
  466. }
  467. INSERT_BEFORE(&(KnownHandle->ListEntry), &EfiFirmwareVolumeList);
  468. return KnownHandle;
  469. }
  470. EFI_STATUS
  471. EfipCoreAddDriverToList (
  472. EFI_FIRMWARE_VOLUME2_PROTOCOL *Volume,
  473. EFI_HANDLE VolumeHandle,
  474. EFI_GUID *DriverName,
  475. EFI_FV_FILETYPE Type
  476. )
  477. /*++
  478. Routine Description:
  479. This routine adds a driver entry to the discovered list.
  480. Arguments:
  481. Volume - Supplies a pointer to the firmware volume.
  482. VolumeHandle - Supplies the firmware volume handle.
  483. DriverName - Supplies a pointer to the GUID of the driver's name.
  484. Type - Supplies the file type.
  485. Return Value:
  486. EFI_SUCCESS on success.
  487. EFI_ALREADY_STARTED if the driver has already been started.
  488. --*/
  489. {
  490. EFI_CORE_DRIVER_ENTRY *DriverEntry;
  491. DriverEntry = EfiCoreAllocateBootPool(sizeof(EFI_CORE_DRIVER_ENTRY));
  492. if (DriverEntry == NULL) {
  493. return EFI_OUT_OF_RESOURCES;
  494. }
  495. EfiCoreSetMemory(DriverEntry, sizeof(EFI_CORE_DRIVER_ENTRY), 0);
  496. if (Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
  497. DriverEntry->IsFirmwareVolumeImage = TRUE;
  498. }
  499. DriverEntry->Magic = EFI_CORE_DRIVER_ENTRY_MAGIC;
  500. EfiCoreCopyMemory(&(DriverEntry->FileName), DriverName, sizeof(EFI_GUID));
  501. DriverEntry->VolumeHandle = VolumeHandle;
  502. DriverEntry->Volume = Volume;
  503. DriverEntry->FileDevicePath =
  504. EfipCoreConvertFirmwareVolumeFileToDevicePath(Volume,
  505. VolumeHandle,
  506. DriverName);
  507. DriverEntry->Dependent = TRUE;
  508. EfiCoreAcquireLock(&EfiDispatcherLock);
  509. INSERT_BEFORE(&(DriverEntry->DriverListEntry), &EfiDiscoveredList);
  510. EfiCoreReleaseLock(&EfiDispatcherLock);
  511. return EFI_SUCCESS;
  512. }
  513. EFI_DEVICE_PATH_PROTOCOL *
  514. EfipCoreConvertFirmwareVolumeFileToDevicePath (
  515. EFI_FIRMWARE_VOLUME2_PROTOCOL *Volume,
  516. EFI_HANDLE VolumeHandle,
  517. EFI_GUID *DriverName
  518. )
  519. /*++
  520. Routine Description:
  521. This routine converts a firmware volume and driver name into an EFI
  522. device path.
  523. Arguments:
  524. Volume - Supplies a pointer to the firmware volume.
  525. VolumeHandle - Supplies the firmware volume handle.
  526. DriverName - Supplies a pointer to the GUID of the driver's name.
  527. Return Value:
  528. Returns a pointer to the file device path.
  529. --*/
  530. {
  531. EFI_DEVICE_PATH_PROTOCOL *FileDevicePath;
  532. EFI_FIRMWARE_VOLUME_FILE_DEVICE_PATH FileNameDevicePath;
  533. EFI_STATUS Status;
  534. EFI_DEVICE_PATH_PROTOCOL *VolumeDevicePath;
  535. Status = EfiCoreHandleProtocol(VolumeHandle,
  536. &EfiDevicePathProtocolGuid,
  537. (VOID **)&VolumeDevicePath);
  538. if (EFI_ERROR(Status)) {
  539. return NULL;
  540. }
  541. //
  542. // Build a device path to the file in the volume.
  543. //
  544. EfiCoreInitializeFirmwareVolumeDevicePathNode(&(FileNameDevicePath.File),
  545. DriverName);
  546. EfiCoreSetDevicePathEndNode(&(FileNameDevicePath.End));
  547. FileDevicePath = EfiCoreAppendDevicePath(
  548. VolumeDevicePath,
  549. (EFI_DEVICE_PATH_PROTOCOL *)&FileNameDevicePath);
  550. return FileDevicePath;
  551. }
  552. VOID
  553. EfipCoreInsertOnScheduledQueue (
  554. PEFI_CORE_DRIVER_ENTRY DriverEntry
  555. )
  556. /*++
  557. Routine Description:
  558. This routine inserts a driver entry onto the scheduled queue.
  559. Arguments:
  560. DriverEntry - Supplies a pointer to the driver entry to schedule.
  561. Return Value:
  562. None.
  563. --*/
  564. {
  565. EfiCoreAcquireLock(&EfiDispatcherLock);
  566. DriverEntry->Dependent = FALSE;
  567. DriverEntry->Scheduled = TRUE;
  568. INSERT_BEFORE(&(DriverEntry->SchedulerListEntry), &EfiScheduledQueue);
  569. EfiCoreReleaseLock(&EfiDispatcherLock);
  570. return;
  571. }