devpathu.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  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. devpathu.c
  9. Abstract:
  10. This module implements device path utilities for the UEFI core.
  11. Author:
  12. Evan Green 5-Mar-2014
  13. Environment:
  14. Firmware
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "ueficore.h"
  20. //
  21. // ---------------------------------------------------------------- Definitions
  22. //
  23. #define DEVICE_PATH_MAX_NODE_COUNT 255
  24. //
  25. // ------------------------------------------------------ Data Type Definitions
  26. //
  27. //
  28. // ----------------------------------------------- Internal Function Prototypes
  29. //
  30. //
  31. // -------------------------------------------------------------------- Globals
  32. //
  33. EFI_GUID EfiDevicePathProtocolGuid = EFI_DEVICE_PATH_PROTOCOL_GUID;
  34. EFI_DEVICE_PATH_PROTOCOL EfiEndDevicePath = {
  35. END_DEVICE_PATH_TYPE,
  36. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  37. END_DEVICE_PATH_LENGTH
  38. };
  39. //
  40. // ------------------------------------------------------------------ Functions
  41. //
  42. EFIAPI
  43. EFI_DEVICE_PATH_PROTOCOL *
  44. EfiCoreDuplicateDevicePath (
  45. CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
  46. )
  47. /*++
  48. Routine Description:
  49. This routine creates a duplicate of the specified path.
  50. Arguments:
  51. DevicePath - Supplies a pointer to the device path instance.
  52. Return Value:
  53. Returns a pointer to the duplicate device path on success.
  54. NULL on allocation failure or if the input device path was null.
  55. --*/
  56. {
  57. VOID *Copy;
  58. UINTN Size;
  59. Size = EfiCoreGetDevicePathSize(DevicePath);
  60. if (Size == 0) {
  61. return NULL;
  62. }
  63. Copy = EfiCoreAllocateBootPool(Size);
  64. if (Copy == NULL) {
  65. return NULL;
  66. }
  67. EfiCoreCopyMemory(Copy, (VOID *)DevicePath, Size);
  68. return Copy;
  69. }
  70. EFIAPI
  71. EFI_DEVICE_PATH_PROTOCOL *
  72. EfiCoreAppendDevicePath (
  73. CONST EFI_DEVICE_PATH_PROTOCOL *First,
  74. CONST EFI_DEVICE_PATH_PROTOCOL *Second
  75. )
  76. /*++
  77. Routine Description:
  78. This routine creates a new path by appending the second device path to the
  79. first. If the first source is NULL and the second is not, then a duplicate
  80. of the second is returned. If the first is not NULL and the second is, a
  81. duplicate of the first is made. If both are NULL, then a copy of an
  82. end-of-device-path is returned.
  83. Arguments:
  84. First - Supplies an optional pointer to the first device path instance.
  85. Second - Supplies an optional pointer to the second device path instance.
  86. Return Value:
  87. Returns a pointer to the duplicate appended device path on success.
  88. NULL on allocation failure.
  89. --*/
  90. {
  91. UINTN FinalSize;
  92. UINTN FirstSize;
  93. EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
  94. EFI_DEVICE_PATH_PROTOCOL *SecondLeg;
  95. UINTN SecondSize;
  96. if (First == NULL) {
  97. if (Second != NULL) {
  98. return EfiCoreDuplicateDevicePath(Second);
  99. } else {
  100. return EfiCoreDuplicateDevicePath(&EfiEndDevicePath);
  101. }
  102. }
  103. if (Second == NULL) {
  104. return EfiCoreDuplicateDevicePath(First);
  105. }
  106. if ((EfiCoreIsDevicePathValid(First, 0) == FALSE) ||
  107. (EfiCoreIsDevicePathValid(Second, 0) == FALSE)) {
  108. return NULL;
  109. }
  110. FirstSize = EfiCoreGetDevicePathSize(First);
  111. SecondSize = EfiCoreGetDevicePathSize(Second);
  112. FinalSize = FirstSize + SecondSize - END_DEVICE_PATH_LENGTH;
  113. NewDevicePath = EfiCoreAllocateBootPool(FinalSize);
  114. if (NewDevicePath == NULL) {
  115. return NULL;
  116. }
  117. EfiCoreCopyMemory(NewDevicePath, (VOID *)First, FirstSize);
  118. //
  119. // Copy over the first end node.
  120. //
  121. SecondLeg = (EFI_DEVICE_PATH_PROTOCOL *)((CHAR8 *)NewDevicePath +
  122. (FirstSize -
  123. END_DEVICE_PATH_LENGTH));
  124. EfiCoreCopyMemory(SecondLeg, (VOID *)Second, SecondSize);
  125. return NewDevicePath;
  126. }
  127. EFIAPI
  128. EFI_DEVICE_PATH_PROTOCOL *
  129. EfiCoreAppendDevicePathInstance (
  130. CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
  131. CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance
  132. )
  133. /*++
  134. Routine Description:
  135. This routine creates a new path by appending the second device path
  136. instance to the first. The end-of-device-path device node is moved after
  137. the end of the appended device path instance and a new
  138. end-of-device-path-instance node is inserted between. If DevicePath is
  139. NULL, then a copy if DevicePathInstance is returned. If the device path
  140. instance is NULL, then NULL is returned. If the device path or device path
  141. instance is invalid, then NULL is returned. If there is not enough memory
  142. to allocate space for the new device path, then NULL is returned. The
  143. memory is allocated from EFI boot services memory. It is the responsibility
  144. of the caller to free the memory allocated.
  145. Arguments:
  146. DevicePath - Supplies an optional pointer to the device path.
  147. DevicePathInstance - Supplies a pointer to the device path instance to
  148. append.
  149. Return Value:
  150. Returns a pointer to the appended device path on success. The caller is
  151. responsible for freeing this newly allocated memory.
  152. NULL on allocation failure.
  153. --*/
  154. {
  155. EFI_DEVICE_PATH_PROTOCOL *End;
  156. UINTN InstanceSize;
  157. EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
  158. UINTN SourceSize;
  159. if (DevicePath == NULL) {
  160. return EfiCoreDuplicateDevicePath(DevicePathInstance);
  161. }
  162. if (DevicePathInstance == NULL) {
  163. return NULL;
  164. }
  165. if ((EfiCoreIsDevicePathValid(DevicePath, 0) == FALSE) ||
  166. (EfiCoreIsDevicePathValid(DevicePathInstance, 0) == FALSE)) {
  167. return NULL;
  168. }
  169. SourceSize = EfiCoreGetDevicePathSize(DevicePath);
  170. InstanceSize = EfiCoreGetDevicePathSize(DevicePathInstance);
  171. NewDevicePath = EfiCoreAllocateBootPool(SourceSize + InstanceSize);
  172. if (NewDevicePath != NULL) {
  173. EfiCoreCopyMemory(NewDevicePath, (VOID *)DevicePath, SourceSize);
  174. End = NewDevicePath;
  175. while (EfiCoreIsDevicePathEnd(End) == FALSE) {
  176. End = EfiCoreGetNextDevicePathNode(End);
  177. }
  178. End->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
  179. End = EfiCoreGetNextDevicePathNode(End);
  180. EfiCoreCopyMemory(End, (VOID *)DevicePathInstance, InstanceSize);
  181. }
  182. return NewDevicePath;
  183. }
  184. EFIAPI
  185. EFI_DEVICE_PATH_PROTOCOL *
  186. EfiCoreAppendDevicePathNode (
  187. CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
  188. CONST EFI_DEVICE_PATH_PROTOCOL *Node
  189. )
  190. /*++
  191. Routine Description:
  192. This routine creates a new device path by appending a copy of the given
  193. device path node to a copy of the given device path in an allocated buffer.
  194. The end-of-device-path device node is moved after the end of the appended
  195. device node. If the node is NULL then a copy of the device path is returned.
  196. If the device path is NULL then a copy of the node, followed by an
  197. end-of-device path device node is returned. If both are NULL then a copy of
  198. an end-of-device-path device node is returned. If there is not enough
  199. memory to allocate space for the new device path, then NULL is returned.
  200. The memory is allocated from EFI boot services memory. It is the
  201. responsibility of the caller to free the memory allocated.
  202. Arguments:
  203. DevicePath - Supplies an optional pointer to the device path.
  204. Node - Supplies an optional pointer to the device path node to append.
  205. Return Value:
  206. Returns a pointer to the appended device path on success. The caller is
  207. responsible for freeing this newly allocated memory.
  208. NULL on allocation failure.
  209. --*/
  210. {
  211. EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
  212. EFI_DEVICE_PATH_PROTOCOL *NextNode;
  213. UINTN NodeLength;
  214. EFI_DEVICE_PATH_PROTOCOL *NodePath;
  215. if (Node == NULL) {
  216. if (DevicePath != NULL) {
  217. return EfiCoreDuplicateDevicePath(DevicePath);
  218. } else {
  219. return EfiCoreDuplicateDevicePath(&EfiEndDevicePath);
  220. }
  221. }
  222. NodeLength = EfiCoreGetDevicePathNodeLength(Node);
  223. //
  224. // Create a copy of the node and add an end node to make it a complete
  225. // device path.
  226. //
  227. NodePath = EfiCoreAllocateBootPool(NodeLength + END_DEVICE_PATH_LENGTH);
  228. if (NodePath == NULL) {
  229. return NULL;
  230. }
  231. EfiCoreCopyMemory(NodePath, (VOID *)Node, NodeLength);
  232. NextNode = EfiCoreGetNextDevicePathNode(NodePath);
  233. EfiCoreSetDevicePathEndNode(NextNode);
  234. //
  235. // Append the two (now complete) paths.
  236. //
  237. NewDevicePath = EfiCoreAppendDevicePath(DevicePath, NodePath);
  238. EfiCoreFreePool(NodePath);
  239. return NewDevicePath;
  240. }
  241. EFIAPI
  242. UINTN
  243. EfiCoreGetDevicePathSize (
  244. CONST VOID *DevicePath
  245. )
  246. /*++
  247. Routine Description:
  248. This routine returns the length of the given device path in bytes.
  249. Arguments:
  250. DevicePath - Supplies a pointer to the device path.
  251. Return Value:
  252. Returns the device path size in bytes.
  253. 0 if the device path is NULL or invalid.
  254. --*/
  255. {
  256. UINTN Size;
  257. CONST EFI_DEVICE_PATH_PROTOCOL *Start;
  258. if (DevicePath == NULL) {
  259. return 0;
  260. }
  261. if (EfiCoreIsDevicePathValid(DevicePath, 0) == FALSE) {
  262. return 0;
  263. }
  264. //
  265. // Search for the end of the device path.
  266. //
  267. Start = DevicePath;
  268. while (EfiCoreIsDevicePathEnd(DevicePath) == FALSE) {
  269. DevicePath = EfiCoreGetNextDevicePathNode(DevicePath);
  270. }
  271. //
  272. // Compute the size and add the end device path entry.
  273. //
  274. Size = ((UINTN)DevicePath - (UINTN)Start) +
  275. EfiCoreGetDevicePathNodeLength(DevicePath);
  276. return Size;
  277. }
  278. EFIAPI
  279. EFI_DEVICE_PATH_PROTOCOL *
  280. EfiCoreGetNextDevicePathNode (
  281. CONST VOID *Node
  282. )
  283. /*++
  284. Routine Description:
  285. This routine returns a pointer to the next node in the device.
  286. Arguments:
  287. Node - Supplies a pointer to the device path node.
  288. Return Value:
  289. Returns a pointer to the device path node that follows this node.
  290. --*/
  291. {
  292. EFI_DEVICE_PATH_PROTOCOL *Next;
  293. Next = (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)Node +
  294. EfiCoreGetDevicePathNodeLength(Node));
  295. return Next;
  296. }
  297. EFIAPI
  298. EFI_DEVICE_PATH_PROTOCOL *
  299. EfiCoreGetNextDevicePathInstance (
  300. EFI_DEVICE_PATH_PROTOCOL **DevicePath,
  301. UINTN *Size
  302. )
  303. /*++
  304. Routine Description:
  305. This routine creates a copy of the current device path instance and returns
  306. a pointer to the next device path instance.
  307. Arguments:
  308. DevicePath - Supplies a pointer that on input contains a pointer to the
  309. device path instance to copy. On output, this will point to the next
  310. device path instance on success or NULL on failure.
  311. Size - Supplies a pointer that on input contains the size of the device
  312. path. On output this value will be updated to contain the remaining
  313. size.
  314. Return Value:
  315. Returns a pointer to the current device path instance (duplicate).
  316. --*/
  317. {
  318. EFI_DEVICE_PATH_PROTOCOL *Path;
  319. EFI_DEVICE_PATH_PROTOCOL *ReturnValue;
  320. UINT8 SubType;
  321. ASSERT(Size != NULL);
  322. if ((DevicePath == NULL) || (*DevicePath == NULL)) {
  323. *Size = 0;
  324. return NULL;
  325. }
  326. if (EfiCoreIsDevicePathValid(*DevicePath, 0) == FALSE) {
  327. return NULL;
  328. }
  329. //
  330. // Find the end of the device path instance.
  331. //
  332. Path = *DevicePath;
  333. while (EfiCoreIsDevicePathEndType(Path) == FALSE) {
  334. Path = EfiCoreGetNextDevicePathNode(Path);
  335. }
  336. //
  337. // Compute the size of the device path instance.
  338. //
  339. *Size = ((UINTN)Path - (UINTN)(*DevicePath)) -
  340. sizeof(EFI_DEVICE_PATH_PROTOCOL);
  341. //
  342. // Make a copy and return the device path instance.
  343. //
  344. SubType = Path->SubType;
  345. Path->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
  346. ReturnValue = EfiCoreDuplicateDevicePath(*DevicePath);
  347. Path->SubType = SubType;
  348. //
  349. // If the device path is an end of entire device path, then another
  350. // instance does not follow, so null out the device path parameter.
  351. //
  352. if (EfiCoreGetDevicePathSubType(Path) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
  353. *DevicePath = NULL;
  354. } else {
  355. *DevicePath = EfiCoreGetNextDevicePathNode(Path);
  356. }
  357. return ReturnValue;
  358. }
  359. EFIAPI
  360. EFI_DEVICE_PATH_PROTOCOL *
  361. EfiCoreGetDevicePathFromHandle (
  362. EFI_HANDLE Handle
  363. )
  364. /*++
  365. Routine Description:
  366. This routine returns the device path protocol instance on the given handle.
  367. Arguments:
  368. Handle - Supplies the handle to get the device path on.
  369. Return Value:
  370. Returns a pointer to the device path protocol on the handle.
  371. NULL on failure.
  372. --*/
  373. {
  374. EFI_DEVICE_PATH_PROTOCOL *Path;
  375. EFI_STATUS Status;
  376. Status = EfiHandleProtocol(Handle,
  377. &EfiDevicePathProtocolGuid,
  378. (VOID **)&Path);
  379. if (EFI_ERROR(Status)) {
  380. Path = NULL;
  381. }
  382. return Path;
  383. }
  384. EFIAPI
  385. BOOLEAN
  386. EfiCoreIsDevicePathValid (
  387. CONST VOID *DevicePath,
  388. UINTN MaxSize
  389. )
  390. /*++
  391. Routine Description:
  392. This routine determines if a device path is valid.
  393. Arguments:
  394. DevicePath - Supplies a pointer to the device path to query.
  395. MaxSize - Supplies the maximum size of the device path structure.
  396. Return Value:
  397. TRUE if the device path is valid.
  398. FALSE if the length of any node is less than the header size, or the length
  399. exceeds the given maximum size (if not zero).
  400. --*/
  401. {
  402. UINTN Count;
  403. UINTN NodeLength;
  404. UINTN Size;
  405. ASSERT(DevicePath != NULL);
  406. Count = 0;
  407. Size = 0;
  408. while (EfiCoreIsDevicePathEnd(DevicePath) == FALSE) {
  409. NodeLength = EfiCoreGetDevicePathNodeLength(DevicePath);
  410. if (NodeLength < sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
  411. return FALSE;
  412. }
  413. if (MaxSize > 0) {
  414. Size += NodeLength;
  415. if (Size + END_DEVICE_PATH_LENGTH > MaxSize) {
  416. return FALSE;
  417. }
  418. }
  419. Count += 1;
  420. if ((DEVICE_PATH_MAX_NODE_COUNT != 0) &&
  421. (Count >= DEVICE_PATH_MAX_NODE_COUNT)) {
  422. return FALSE;
  423. }
  424. DevicePath = EfiCoreGetNextDevicePathNode(DevicePath);
  425. }
  426. if (EfiCoreGetDevicePathNodeLength(DevicePath) != END_DEVICE_PATH_LENGTH) {
  427. return FALSE;
  428. }
  429. return TRUE;
  430. }
  431. EFIAPI
  432. BOOLEAN
  433. EfiCoreIsDevicePathEnd (
  434. CONST VOID *Node
  435. )
  436. /*++
  437. Routine Description:
  438. This routine determines if a device path node is an end node of an
  439. entire device path.
  440. Arguments:
  441. Node - Supplies a pointer to the device path node.
  442. Return Value:
  443. TRUE if this node is the end of the entire device path.
  444. FALSE if this node is not the end of the entire device path.
  445. --*/
  446. {
  447. if ((EfiCoreIsDevicePathEndType(Node) != FALSE) &&
  448. (EfiCoreGetDevicePathSubType(Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE)) {
  449. return TRUE;
  450. }
  451. return FALSE;
  452. }
  453. EFIAPI
  454. BOOLEAN
  455. EfiCoreIsDevicePathEndInstance (
  456. CONST VOID *Node
  457. )
  458. /*++
  459. Routine Description:
  460. This routine determines if a device path node is an end node of a
  461. device path instance.
  462. Arguments:
  463. Node - Supplies a pointer to the device path node.
  464. Return Value:
  465. TRUE if this node is the end of the device path instance.
  466. FALSE if this node is not the end of the device path instance.
  467. --*/
  468. {
  469. if ((EfiCoreIsDevicePathEndType(Node) != FALSE) &&
  470. (EfiCoreGetDevicePathSubType(Node) ==
  471. END_INSTANCE_DEVICE_PATH_SUBTYPE)) {
  472. return TRUE;
  473. }
  474. return FALSE;
  475. }
  476. EFIAPI
  477. BOOLEAN
  478. EfiCoreIsDevicePathEndType (
  479. CONST VOID *Node
  480. )
  481. /*++
  482. Routine Description:
  483. This routine determines if a device path node is the end device path type.
  484. Arguments:
  485. Node - Supplies a pointer to the device path node.
  486. Return Value:
  487. TRUE if this node's type is the end type.
  488. FALSE if this node's type is not the end type.
  489. --*/
  490. {
  491. if (EfiCoreGetDevicePathType(Node) == END_DEVICE_PATH_TYPE) {
  492. return TRUE;
  493. }
  494. return FALSE;
  495. }
  496. EFIAPI
  497. UINT8
  498. EfiCoreGetDevicePathType (
  499. CONST VOID *Node
  500. )
  501. /*++
  502. Routine Description:
  503. This routine returns the device path type for the given node.
  504. Arguments:
  505. Node - Supplies a pointer to the device path node.
  506. Return Value:
  507. Returns the node's type.
  508. --*/
  509. {
  510. ASSERT(Node != NULL);
  511. return ((EFI_DEVICE_PATH_PROTOCOL *)Node)->Type;
  512. }
  513. EFIAPI
  514. UINT8
  515. EfiCoreGetDevicePathSubType (
  516. CONST VOID *Node
  517. )
  518. /*++
  519. Routine Description:
  520. This routine returns the device path sub-type for the given node.
  521. Arguments:
  522. Node - Supplies a pointer to the device path node.
  523. Return Value:
  524. Returns the node's sub-type.
  525. --*/
  526. {
  527. ASSERT(Node != NULL);
  528. return ((EFI_DEVICE_PATH_PROTOCOL *)Node)->SubType;
  529. }
  530. EFIAPI
  531. UINTN
  532. EfiCoreGetDevicePathNodeLength (
  533. CONST VOID *Node
  534. )
  535. /*++
  536. Routine Description:
  537. This routine returns the length of the given device path node.
  538. Arguments:
  539. Node - Supplies a pointer to the device path node.
  540. Return Value:
  541. Returns the device path node length.
  542. --*/
  543. {
  544. ASSERT(Node != NULL);
  545. return ((EFI_DEVICE_PATH_PROTOCOL *)Node)->Length;
  546. }
  547. EFIAPI
  548. VOID
  549. EfiCoreInitializeFirmwareVolumeDevicePathNode (
  550. MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FirmwareFile,
  551. EFI_GUID *NameGuid
  552. )
  553. /*++
  554. Routine Description:
  555. This routine initializes a firmware volume file path.
  556. Arguments:
  557. FirmwareFile - Supplies a pointer to the device path node to initialize.
  558. NameGuid - Supplies a pointer to the name of the file.
  559. Return Value:
  560. None.
  561. --*/
  562. {
  563. ASSERT((FirmwareFile != NULL) && (NameGuid != NULL));
  564. FirmwareFile->Header.Type = MEDIA_DEVICE_PATH;
  565. FirmwareFile->Header.SubType = MEDIA_PIWG_FW_FILE_DP;
  566. EfiCoreSetDevicePathNodeLength(&(FirmwareFile->Header),
  567. sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));
  568. EfiCoreCopyMemory(&(FirmwareFile->FvFileName), NameGuid, sizeof(EFI_GUID));
  569. return;
  570. }
  571. EFIAPI
  572. EFI_DEVICE_PATH_PROTOCOL *
  573. EfiCoreCreateFileDevicePath (
  574. EFI_HANDLE Device,
  575. CONST CHAR16 *FileName
  576. )
  577. /*++
  578. Routine Description:
  579. This routine creates a device path for a file and appends it to an existing
  580. device path. If the given device is a valid handle that contains a device
  581. path protocol, then a device path for the file specified by the given file
  582. name is allocated and appended to the device path associated with the
  583. given handle. The allocated device path is returned. If the device is NULL
  584. or the device is a handle that does not support the device path protocol,
  585. then a device path containing a single device path node for the file
  586. specified by the file name is allocated and returned. The memory for the
  587. new device path is allocated from EFI boot services memory. It is the
  588. responsibility of the caller to free the memory allocated.
  589. Arguments:
  590. Device - Supplies an optional device handle.
  591. FileName - Supplies a pointer to a null-terminated file path string.
  592. Return Value:
  593. Returns a pointer to the created device path.
  594. --*/
  595. {
  596. UINTN AllocationSize;
  597. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  598. EFI_DEVICE_PATH_PROTOCOL *End;
  599. EFI_DEVICE_PATH_PROTOCOL *FileDevicePath;
  600. FILEPATH_DEVICE_PATH *FilePath;
  601. UINTN Size;
  602. DevicePath = NULL;
  603. Size = (EfiCoreStringLength((VOID *)FileName) + 1) * sizeof(CHAR16);
  604. AllocationSize = Size + SIZE_OF_FILEPATH_DEVICE_PATH +
  605. END_DEVICE_PATH_LENGTH;
  606. FileDevicePath = EfiCoreAllocateBootPool(AllocationSize);
  607. if (FileDevicePath != NULL) {
  608. FilePath = (FILEPATH_DEVICE_PATH *)FileDevicePath;
  609. FilePath->Header.Type = MEDIA_DEVICE_PATH;
  610. FilePath->Header.SubType = MEDIA_FILEPATH_DP;
  611. EfiCoreCopyMemory(&(FilePath->PathName), (VOID *)FileName, Size);
  612. EfiCoreSetDevicePathNodeLength(&(FilePath->Header),
  613. Size + SIZE_OF_FILEPATH_DEVICE_PATH);
  614. End = EfiCoreGetNextDevicePathNode(&(FilePath->Header));
  615. EfiCoreSetDevicePathEndNode(End);
  616. if (Device != NULL) {
  617. DevicePath = EfiCoreGetDevicePathFromHandle(Device);
  618. }
  619. DevicePath = EfiCoreAppendDevicePath(DevicePath, FileDevicePath);
  620. EfiCoreFreePool(FileDevicePath);
  621. }
  622. return DevicePath;
  623. }
  624. EFIAPI
  625. EFI_GUID *
  626. EfiCoreGetNameGuidFromFirmwareVolumeDevicePathNode (
  627. CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *DevicePathNode
  628. )
  629. /*++
  630. Routine Description:
  631. This routine returns the file name GUID out of a firmware volume file
  632. path node.
  633. Arguments:
  634. DevicePathNode - Supplies a pointer to the device path node.
  635. Return Value:
  636. Returns a pointer to the file name GUID.
  637. --*/
  638. {
  639. ASSERT(DevicePathNode != NULL);
  640. if ((EfiCoreGetDevicePathType(&(DevicePathNode->Header)) ==
  641. MEDIA_DEVICE_PATH) &&
  642. (EfiCoreGetDevicePathSubType(&(DevicePathNode->Header)) ==
  643. MEDIA_PIWG_FW_FILE_DP)) {
  644. return (EFI_GUID *)(&(DevicePathNode->FvFileName));
  645. }
  646. return NULL;
  647. }
  648. EFIAPI
  649. UINT16
  650. EfiCoreSetDevicePathNodeLength (
  651. VOID *Node,
  652. UINTN Length
  653. )
  654. /*++
  655. Routine Description:
  656. This routine sets a device path node length.
  657. Arguments:
  658. Node - Supplies a pointer to the device path header.
  659. Length - Supplies the length to set.
  660. Return Value:
  661. Returns the length value.
  662. --*/
  663. {
  664. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  665. ASSERT((Node != 0) && (Length >= sizeof(EFI_DEVICE_PATH_PROTOCOL)) &&
  666. (Length < 64 * 1024));
  667. DevicePath = Node;
  668. DevicePath->Length = Length;
  669. return DevicePath->Length;
  670. }
  671. EFIAPI
  672. VOID
  673. EfiCoreSetDevicePathEndNode (
  674. VOID *Node
  675. )
  676. /*++
  677. Routine Description:
  678. This routine sets the given device path node as an end of the entire
  679. device path.
  680. Arguments:
  681. Node - Supplies a pointer to the device path header.
  682. Return Value:
  683. None.
  684. --*/
  685. {
  686. ASSERT(Node != NULL);
  687. EfiCoreCopyMemory(Node, &EfiEndDevicePath, sizeof(EfiEndDevicePath));
  688. return;
  689. }
  690. //
  691. // --------------------------------------------------------- Internal Functions
  692. //