part.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. part.c
  5. Abstract:
  6. This module implements support for the partition driver in UEFI.
  7. Author:
  8. Evan Green 19-Mar-2014
  9. Environment:
  10. Firmware
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "ueficore.h"
  16. #include "part.h"
  17. //
  18. // ---------------------------------------------------------------- Definitions
  19. //
  20. //
  21. // ------------------------------------------------------ Data Type Definitions
  22. //
  23. //
  24. // ----------------------------------------------- Internal Function Prototypes
  25. //
  26. EFIAPI
  27. EFI_STATUS
  28. EfiPartitionSupported (
  29. EFI_DRIVER_BINDING_PROTOCOL *This,
  30. EFI_HANDLE ControllerHandle,
  31. EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  32. );
  33. EFIAPI
  34. EFI_STATUS
  35. EfiPartitionStart (
  36. EFI_DRIVER_BINDING_PROTOCOL *This,
  37. EFI_HANDLE ControllerHandle,
  38. EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  39. );
  40. EFIAPI
  41. EFI_STATUS
  42. EfiPartitionStop (
  43. EFI_DRIVER_BINDING_PROTOCOL *This,
  44. EFI_HANDLE ControllerHandle,
  45. UINTN NumberOfChildren,
  46. EFI_HANDLE *ChildHandleBuffer
  47. );
  48. EFIAPI
  49. EFI_STATUS
  50. EfiPartitionReset (
  51. EFI_BLOCK_IO_PROTOCOL *This,
  52. BOOLEAN ExtendedVerification
  53. );
  54. EFIAPI
  55. EFI_STATUS
  56. EfiPartitionReadBlocks (
  57. EFI_BLOCK_IO_PROTOCOL *This,
  58. UINT32 MediaId,
  59. EFI_LBA Lba,
  60. UINTN BufferSize,
  61. VOID *Buffer
  62. );
  63. EFIAPI
  64. EFI_STATUS
  65. EfiPartitionWriteBlocks (
  66. EFI_BLOCK_IO_PROTOCOL *This,
  67. UINT32 MediaId,
  68. EFI_LBA Lba,
  69. UINTN BufferSize,
  70. VOID *Buffer
  71. );
  72. EFIAPI
  73. EFI_STATUS
  74. EfiPartitionFlushBlocks (
  75. EFI_BLOCK_IO_PROTOCOL *This
  76. );
  77. EFI_STATUS
  78. EfipPartitionProbeMediaStatus (
  79. EFI_DISK_IO_PROTOCOL *DiskIo,
  80. UINT32 MediaId,
  81. EFI_STATUS DefaultStatus
  82. );
  83. //
  84. // -------------------------------------------------------------------- Globals
  85. //
  86. EFI_DRIVER_BINDING_PROTOCOL EfiPartitionDriverBinding = {
  87. EfiPartitionSupported,
  88. EfiPartitionStart,
  89. EfiPartitionStop,
  90. 0xB,
  91. NULL,
  92. NULL
  93. };
  94. EFI_PARTITION_DETECT_ROUTINE EfiPartitionDetectRoutines[] = {
  95. EfiPartitionDetectGpt,
  96. EfiPartitionDetectElTorito,
  97. EfiPartitionDetectMbr,
  98. NULL
  99. };
  100. //
  101. // ------------------------------------------------------------------ Functions
  102. //
  103. EFIAPI
  104. EFI_STATUS
  105. EfiPartitionDriverEntry (
  106. EFI_HANDLE ImageHandle,
  107. EFI_SYSTEM_TABLE *SystemTable
  108. )
  109. /*++
  110. Routine Description:
  111. This routine is the entry point into the partition driver.
  112. Arguments:
  113. ImageHandle - Supplies the driver image handle.
  114. SystemTable - Supplies a pointer to the EFI system table.
  115. Return Value:
  116. EFI status code.
  117. --*/
  118. {
  119. EFI_STATUS Status;
  120. EfiPartitionDriverBinding.ImageHandle = ImageHandle;
  121. EfiPartitionDriverBinding.DriverBindingHandle = ImageHandle;
  122. Status = EfiInstallMultipleProtocolInterfaces(
  123. &(EfiPartitionDriverBinding.DriverBindingHandle),
  124. &EfiDriverBindingProtocolGuid,
  125. &EfiPartitionDriverBinding,
  126. NULL);
  127. return Status;
  128. }
  129. EFI_STATUS
  130. EfiPartitionInstallChildHandle (
  131. EFI_DRIVER_BINDING_PROTOCOL *This,
  132. EFI_HANDLE ParentHandle,
  133. EFI_DISK_IO_PROTOCOL *DiskIo,
  134. EFI_BLOCK_IO_PROTOCOL *BlockIo,
  135. EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
  136. EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
  137. EFI_LBA Start,
  138. EFI_LBA End,
  139. UINT32 BlockSize,
  140. BOOLEAN EfiSystemPartition
  141. )
  142. /*++
  143. Routine Description:
  144. This routine creates a new partition child handle for a logical block
  145. device that represents a partition.
  146. Arguments:
  147. This - Supplies a pointer to the driver binding protocol instance.
  148. ParentHandle - Supplies the parent handle for the new child.
  149. DiskIo - Supplies a pointer to the parent disk I/O protocol.
  150. BlockIo - Supplies a pointer to the block I/O protocol.
  151. ParentDevicePath - Supplies a pointer to the parent device path.
  152. DevicePathNode - Supplies the child device path node.
  153. Start - Supplies the starting LBA of the partition.
  154. End - Supplies the ending LBA of the partition, inclusive.
  155. BlockSize - Supplies the disk block size.
  156. EfiSystemPartition - Supplies a boolean indicating if this is an EFI
  157. system partition.
  158. Return Value:
  159. EFI status code.
  160. --*/
  161. {
  162. PEFI_PARTITION_DATA Private;
  163. EFI_STATUS Status;
  164. Status = EFI_SUCCESS;
  165. Private = EfiCoreAllocateBootPool(sizeof(EFI_PARTITION_DATA));
  166. if (Private == NULL) {
  167. return EFI_OUT_OF_RESOURCES;
  168. }
  169. EfiSetMem(Private, sizeof(EFI_PARTITION_DATA), 0);
  170. Private->Magic = EFI_PARTITION_DATA_MAGIC;
  171. Private->Start = Start * BlockIo->Media->BlockSize;
  172. Private->End = (End + 1) * BlockIo->Media->BlockSize;
  173. Private->BlockSize = BlockSize;
  174. Private->ParentBlockIo = BlockIo;
  175. Private->ParentDiskIo = DiskIo;
  176. //
  177. // Initialize the Block I/O data.
  178. //
  179. Private->BlockIo.Revision = BlockIo->Revision;
  180. Private->BlockIo.Media = &(Private->Media);
  181. EfiCopyMem(Private->BlockIo.Media,
  182. BlockIo->Media,
  183. sizeof(EFI_BLOCK_IO_MEDIA));
  184. Private->BlockIo.Reset = EfiPartitionReset;
  185. Private->BlockIo.ReadBlocks = EfiPartitionReadBlocks;
  186. Private->BlockIo.WriteBlocks = EfiPartitionWriteBlocks;
  187. Private->BlockIo.FlushBlocks = EfiPartitionFlushBlocks;
  188. //
  189. // Initialize the media.
  190. //
  191. Private->Media.RemovableMedia = BlockIo->Media->RemovableMedia;
  192. Private->Media.ReadOnly = BlockIo->Media->ReadOnly;
  193. Private->Media.WriteCaching = BlockIo->Media->WriteCaching;
  194. Private->Media.IoAlign = 0;
  195. Private->Media.LogicalPartition = TRUE;
  196. Private->Media.LastBlock = ALIGN_VALUE(End - Start + 1, BlockSize) - 1;
  197. Private->Media.BlockSize = (UINT32)BlockSize;
  198. //
  199. // Per UEFI spec, set the lowest aligned LBA, logical blocks per physical
  200. // block, and optimal transfer length granularity to zero for logical
  201. // partitions.
  202. //
  203. if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION2) {
  204. Private->Media.LowestAlignedLba = 0;
  205. Private->Media.LogicalBlocksPerPhysicalBlock = 0;
  206. }
  207. Private->DevicePath = EfiCoreAppendDevicePathNode(ParentDevicePath,
  208. DevicePathNode);
  209. if (Private->DevicePath == NULL) {
  210. EfiFreePool(Private);
  211. return EFI_OUT_OF_RESOURCES;
  212. }
  213. if (EfiSystemPartition != FALSE) {
  214. Private->EspGuid = &EfiPartitionTypeSystemPartitionGuid;
  215. }
  216. //
  217. // Create the new handle.
  218. //
  219. Status = EfiInstallMultipleProtocolInterfaces(&(Private->Handle),
  220. &EfiDevicePathProtocolGuid,
  221. Private->DevicePath,
  222. &EfiBlockIoProtocolGuid,
  223. &(Private->BlockIo),
  224. Private->EspGuid,
  225. NULL,
  226. NULL);
  227. if (!EFI_ERROR(Status)) {
  228. Status = EfiOpenProtocol(ParentHandle,
  229. &EfiDiskIoProtocolGuid,
  230. (VOID **)&DiskIo,
  231. This->DriverBindingHandle,
  232. Private->Handle,
  233. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
  234. } else {
  235. EfiFreePool(Private->DevicePath);
  236. EfiFreePool(Private);
  237. }
  238. return Status;
  239. }
  240. //
  241. // --------------------------------------------------------- Internal Functions
  242. //
  243. EFIAPI
  244. EFI_STATUS
  245. EfiPartitionSupported (
  246. EFI_DRIVER_BINDING_PROTOCOL *This,
  247. EFI_HANDLE ControllerHandle,
  248. EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  249. )
  250. /*++
  251. Routine Description:
  252. This routine tests to see if the partition driver supports this new
  253. controller handle. Any controller handle that contains a block I/O and
  254. disk I/O protocol is supported.
  255. Arguments:
  256. This - Supplies a pointer to the driver binding instance.
  257. ControllerHandle - Supplies the new controller handle to test.
  258. RemainingDevicePath - Supplies an optional parameter to pick a specific
  259. child device to start.
  260. Return Value:
  261. EFI status code.
  262. --*/
  263. {
  264. EFI_DISK_IO_PROTOCOL *DiskIo;
  265. EFI_DEV_PATH *Node;
  266. EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
  267. EFI_STATUS Status;
  268. if (RemainingDevicePath != NULL) {
  269. if (EfiCoreIsDevicePathEnd(RemainingDevicePath) == FALSE) {
  270. Node = (EFI_DEV_PATH *)RemainingDevicePath;
  271. if ((Node->DevPath.Type != MEDIA_DEVICE_PATH) ||
  272. (Node->DevPath.SubType != MEDIA_HARDDRIVE_DP) ||
  273. (EfiCoreGetDevicePathNodeLength(&(Node->DevPath)) !=
  274. sizeof(HARDDRIVE_DEVICE_PATH))) {
  275. return EFI_UNSUPPORTED;
  276. }
  277. }
  278. }
  279. //
  280. // Try to open the abstractions needed to support partitions. Start by
  281. // opening the disk I/O protocol, the least common.
  282. //
  283. Status = EfiOpenProtocol(ControllerHandle,
  284. &EfiDiskIoProtocolGuid,
  285. (VOID **)&DiskIo,
  286. This->DriverBindingHandle,
  287. ControllerHandle,
  288. EFI_OPEN_PROTOCOL_BY_DRIVER);
  289. if (Status == EFI_ALREADY_STARTED) {
  290. return EFI_SUCCESS;
  291. }
  292. if (EFI_ERROR(Status)) {
  293. return Status;
  294. }
  295. EfiCloseProtocol(ControllerHandle,
  296. &EfiDiskIoProtocolGuid,
  297. This->DriverBindingHandle,
  298. ControllerHandle);
  299. //
  300. // Also open up the device path protocol.
  301. //
  302. Status = EfiOpenProtocol(ControllerHandle,
  303. &EfiDevicePathProtocolGuid,
  304. (VOID **)&ParentDevicePath,
  305. This->DriverBindingHandle,
  306. ControllerHandle,
  307. EFI_OPEN_PROTOCOL_BY_DRIVER);
  308. if (Status == EFI_ALREADY_STARTED) {
  309. return EFI_SUCCESS;
  310. }
  311. if (EFI_ERROR(Status)) {
  312. return Status;
  313. }
  314. EfiCloseProtocol(ControllerHandle,
  315. &EfiDevicePathProtocolGuid,
  316. This->DriverBindingHandle,
  317. ControllerHandle);
  318. //
  319. // Open Block I/O.
  320. //
  321. Status = EfiOpenProtocol(ControllerHandle,
  322. &EfiBlockIoProtocolGuid,
  323. NULL,
  324. This->DriverBindingHandle,
  325. ControllerHandle,
  326. EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
  327. if (EFI_ERROR(Status)) {
  328. return Status;
  329. }
  330. return EFI_SUCCESS;
  331. }
  332. EFIAPI
  333. EFI_STATUS
  334. EfiPartitionStart (
  335. EFI_DRIVER_BINDING_PROTOCOL *This,
  336. EFI_HANDLE ControllerHandle,
  337. EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  338. )
  339. /*++
  340. Routine Description:
  341. This routine starts a partition driver on a raw Block I/O device.
  342. Arguments:
  343. This - Supplies a pointer to the driver binding protocol instance.
  344. ControllerHandle - Supplies the handle of the controller to start. This
  345. handle must support a protocol interface that supplies an I/O
  346. abstraction to the driver.
  347. RemainingDevicePath - Supplies an optional pointer to the remaining
  348. portion of a device path.
  349. Return Value:
  350. EFI_SUCCESS if the device was started.
  351. EFI_DEVICE_ERROR if the device could not be started due to a device error.
  352. EFI_OUT_OF_RESOURCES if an allocation failed.
  353. Other error codes if the driver failed to start the device.
  354. --*/
  355. {
  356. EFI_BLOCK_IO_PROTOCOL *BlockIo;
  357. EFI_DISK_IO_PROTOCOL *DiskIo;
  358. BOOLEAN MediaPresent;
  359. EFI_TPL OldTpl;
  360. EFI_STATUS OpenStatus;
  361. EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
  362. EFI_PARTITION_DETECT_ROUTINE *Routine;
  363. EFI_STATUS Status;
  364. OldTpl = EfiRaiseTPL(TPL_CALLBACK);
  365. if (RemainingDevicePath != NULL) {
  366. if (EfiCoreIsDevicePathEnd(RemainingDevicePath) != FALSE) {
  367. Status = EFI_SUCCESS;
  368. goto PartitionStartEnd;
  369. }
  370. }
  371. //
  372. // Open up Block I/O.
  373. //
  374. Status = EfiOpenProtocol(ControllerHandle,
  375. &EfiBlockIoProtocolGuid,
  376. (VOID **)&BlockIo,
  377. This->DriverBindingHandle,
  378. ControllerHandle,
  379. EFI_OPEN_PROTOCOL_GET_PROTOCOL);
  380. if (EFI_ERROR(Status)) {
  381. goto PartitionStartEnd;
  382. }
  383. //
  384. // Get the device path.
  385. //
  386. Status = EfiOpenProtocol(ControllerHandle,
  387. &EfiDevicePathProtocolGuid,
  388. (VOID **)&ParentDevicePath,
  389. This->DriverBindingHandle,
  390. ControllerHandle,
  391. EFI_OPEN_PROTOCOL_BY_DRIVER);
  392. if ((EFI_ERROR(Status)) && (Status != EFI_ALREADY_STARTED)) {
  393. goto PartitionStartEnd;
  394. }
  395. //
  396. // Open Disk I/O.
  397. //
  398. Status = EfiOpenProtocol(ControllerHandle,
  399. &EfiDiskIoProtocolGuid,
  400. (VOID **)&DiskIo,
  401. This->DriverBindingHandle,
  402. ControllerHandle,
  403. EFI_OPEN_PROTOCOL_BY_DRIVER);
  404. if ((EFI_ERROR(Status)) && (Status != EFI_ALREADY_STARTED)) {
  405. EfiCloseProtocol(ControllerHandle,
  406. &EfiDevicePathProtocolGuid,
  407. This->DriverBindingHandle,
  408. ControllerHandle);
  409. goto PartitionStartEnd;
  410. }
  411. OpenStatus = Status;
  412. //
  413. // Try to read blocks when there's media or it's a removable physical
  414. // partition.
  415. //
  416. Status = EFI_UNSUPPORTED;
  417. MediaPresent = BlockIo->Media->MediaPresent;
  418. if ((MediaPresent != FALSE) ||
  419. ((BlockIo->Media->RemovableMedia != FALSE) &&
  420. (BlockIo->Media->LogicalPartition == FALSE))) {
  421. //
  422. // Try for GPT, El Torito, and then legacy MBR partition types.
  423. //
  424. Routine = &(EfiPartitionDetectRoutines[0]);
  425. while (*Routine != NULL) {
  426. Status = (*Routine)(This,
  427. ControllerHandle,
  428. DiskIo,
  429. BlockIo,
  430. ParentDevicePath);
  431. if ((!EFI_ERROR(Status)) ||
  432. (Status == EFI_MEDIA_CHANGED) ||
  433. (Status == EFI_NO_MEDIA)) {
  434. break;
  435. }
  436. Routine += 1;
  437. }
  438. }
  439. //
  440. // In the case that the driver is already started, the device path and disk
  441. // I/O are not actually opened by this driver. So, don't try and close
  442. // them, since they are not owned here.
  443. //
  444. if ((EFI_ERROR(Status)) && (!EFI_ERROR(OpenStatus)) &&
  445. (Status != EFI_MEDIA_CHANGED) &&
  446. ((MediaPresent == FALSE) || (Status != EFI_NO_MEDIA))) {
  447. EfiCloseProtocol(ControllerHandle,
  448. &EfiDiskIoProtocolGuid,
  449. This->DriverBindingHandle,
  450. ControllerHandle);
  451. EfiCloseProtocol(ControllerHandle,
  452. &EfiDevicePathProtocolGuid,
  453. This->DriverBindingHandle,
  454. ControllerHandle);
  455. }
  456. PartitionStartEnd:
  457. EfiRestoreTPL(OldTpl);
  458. return Status;
  459. }
  460. EFIAPI
  461. EFI_STATUS
  462. EfiPartitionStop (
  463. EFI_DRIVER_BINDING_PROTOCOL *This,
  464. EFI_HANDLE ControllerHandle,
  465. UINTN NumberOfChildren,
  466. EFI_HANDLE *ChildHandleBuffer
  467. )
  468. /*++
  469. Routine Description:
  470. This routine stops a partition driver device, stopping any child handles
  471. created by this driver.
  472. Arguments:
  473. This - Supplies a pointer to the driver binding protocol instance.
  474. ControllerHandle - Supplies the handle of the device being stopped. The
  475. handle must support a bus specific I/O protocol for the driver to use
  476. to stop the device.
  477. NumberOfChildren - Supplies the number of child devices in the child handle
  478. buffer.
  479. ChildHandleBuffer - Supplies an optional array of child device handles to
  480. be freed. This can be NULL if the number of children specified is zero.
  481. Return Value:
  482. EFI_SUCCESS if the device was stopped.
  483. EFI_DEVICE_ERROR if the device could not be stopped due to a device error.
  484. --*/
  485. {
  486. BOOLEAN AllChildrenStopped;
  487. EFI_BLOCK_IO_PROTOCOL *BlockIo;
  488. EFI_DISK_IO_PROTOCOL *DiskIo;
  489. UINTN Index;
  490. PEFI_PARTITION_DATA Private;
  491. EFI_STATUS Status;
  492. BlockIo = NULL;
  493. Private = NULL;
  494. if (NumberOfChildren == 0) {
  495. EfiCloseProtocol(ControllerHandle,
  496. &EfiDiskIoProtocolGuid,
  497. This->DriverBindingHandle,
  498. ControllerHandle);
  499. EfiCloseProtocol(ControllerHandle,
  500. &EfiDevicePathProtocolGuid,
  501. This->DriverBindingHandle,
  502. ControllerHandle);
  503. return EFI_SUCCESS;
  504. }
  505. AllChildrenStopped = TRUE;
  506. for (Index = 0; Index < NumberOfChildren; Index += 1) {
  507. EfiOpenProtocol(ChildHandleBuffer[Index],
  508. &EfiBlockIoProtocolGuid,
  509. (VOID **)&BlockIo,
  510. This->DriverBindingHandle,
  511. ControllerHandle,
  512. EFI_OPEN_PROTOCOL_GET_PROTOCOL);
  513. Private = EFI_PARTITION_DATA_FROM_THIS(BlockIo);
  514. ASSERT(Private->Magic == EFI_PARTITION_DATA_MAGIC);
  515. EfiCloseProtocol(ControllerHandle,
  516. &EfiDiskIoProtocolGuid,
  517. This->DriverBindingHandle,
  518. ChildHandleBuffer[Index]);
  519. BlockIo->FlushBlocks(BlockIo);
  520. Status = EfiUninstallMultipleProtocolInterfaces(
  521. ChildHandleBuffer[Index],
  522. &EfiDevicePathProtocolGuid,
  523. Private->DevicePath,
  524. &EfiBlockIoProtocolGuid,
  525. &(Private->BlockIo),
  526. NULL,
  527. NULL);
  528. if (EFI_ERROR(Status)) {
  529. EfiOpenProtocol(ControllerHandle,
  530. &EfiDiskIoProtocolGuid,
  531. (VOID **)&DiskIo,
  532. This->DriverBindingHandle,
  533. ChildHandleBuffer[Index],
  534. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
  535. AllChildrenStopped = FALSE;
  536. } else {
  537. EfiFreePool(Private->DevicePath);
  538. EfiFreePool(Private);
  539. }
  540. }
  541. if (AllChildrenStopped == FALSE) {
  542. return EFI_DEVICE_ERROR;
  543. }
  544. return EFI_SUCCESS;
  545. }
  546. EFIAPI
  547. EFI_STATUS
  548. EfiPartitionReset (
  549. EFI_BLOCK_IO_PROTOCOL *This,
  550. BOOLEAN ExtendedVerification
  551. )
  552. /*++
  553. Routine Description:
  554. This routine resets the block device.
  555. Arguments:
  556. This - Supplies a pointer to the protocol instance.
  557. ExtendedVerification - Supplies a boolean indicating whether or not the
  558. driver should perform diagnostics on reset.
  559. Return Value:
  560. EFI_SUCCESS on success.
  561. EFI_DEVICE_ERROR if the device had an error and could not complete the
  562. request.
  563. --*/
  564. {
  565. PEFI_PARTITION_DATA Private;
  566. EFI_STATUS Status;
  567. Private = EFI_PARTITION_DATA_FROM_THIS(This);
  568. Status = Private->ParentBlockIo->Reset(Private->ParentBlockIo,
  569. ExtendedVerification);
  570. return Status;
  571. }
  572. EFIAPI
  573. EFI_STATUS
  574. EfiPartitionReadBlocks (
  575. EFI_BLOCK_IO_PROTOCOL *This,
  576. UINT32 MediaId,
  577. EFI_LBA Lba,
  578. UINTN BufferSize,
  579. VOID *Buffer
  580. )
  581. /*++
  582. Routine Description:
  583. This routine performs a block I/O read from the device.
  584. Arguments:
  585. This - Supplies a pointer to the protocol instance.
  586. MediaId - Supplies the media identifier, which changes each time the media
  587. is replaced.
  588. Lba - Supplies the logical block address of the read.
  589. BufferSize - Supplies the size of the buffer in bytes.
  590. Buffer - Supplies the buffer where the read data will be returned.
  591. Return Value:
  592. EFI_SUCCESS on success.
  593. EFI_DEVICE_ERROR if the device had an error and could not complete the
  594. request.
  595. EFI_NO_MEDIA if there is no media in the device.
  596. EFI_MEDIA_CHANGED if the media ID does not match the current device.
  597. EFI_BAD_BUFFER_SIZE if the buffer was not a multiple of the device block
  598. size.
  599. EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid,
  600. or the buffer is not properly aligned.
  601. --*/
  602. {
  603. UINT64 Offset;
  604. PEFI_PARTITION_DATA Private;
  605. EFI_STATUS Status;
  606. Private = EFI_PARTITION_DATA_FROM_THIS(This);
  607. ASSERT(Private->Magic == EFI_PARTITION_DATA_MAGIC);
  608. if ((BufferSize % Private->BlockSize) != 0) {
  609. Status = EfipPartitionProbeMediaStatus(Private->ParentDiskIo,
  610. MediaId,
  611. EFI_BAD_BUFFER_SIZE);
  612. return Status;
  613. }
  614. Offset = Lba * Private->BlockSize + Private->Start;
  615. if (Offset + BufferSize > Private->End) {
  616. Status = EfipPartitionProbeMediaStatus(Private->ParentDiskIo,
  617. MediaId,
  618. EFI_INVALID_PARAMETER);
  619. }
  620. //
  621. // Use the disk I/O protocol because some kinds of partitions have
  622. // different block sizes than their parents.
  623. //
  624. Status = Private->ParentDiskIo->ReadDisk(Private->ParentDiskIo,
  625. MediaId,
  626. Offset,
  627. BufferSize,
  628. Buffer);
  629. return Status;
  630. }
  631. EFIAPI
  632. EFI_STATUS
  633. EfiPartitionWriteBlocks (
  634. EFI_BLOCK_IO_PROTOCOL *This,
  635. UINT32 MediaId,
  636. EFI_LBA Lba,
  637. UINTN BufferSize,
  638. VOID *Buffer
  639. )
  640. /*++
  641. Routine Description:
  642. This routine performs a block I/O write to the device.
  643. Arguments:
  644. This - Supplies a pointer to the protocol instance.
  645. MediaId - Supplies the media identifier, which changes each time the media
  646. is replaced.
  647. Lba - Supplies the logical block address of the write.
  648. BufferSize - Supplies the size of the buffer in bytes.
  649. Buffer - Supplies the buffer containing the data to write.
  650. Return Value:
  651. EFI_SUCCESS on success.
  652. EFI_WRITE_PROTECTED if the device cannot be written to.
  653. EFI_DEVICE_ERROR if the device had an error and could not complete the
  654. request.
  655. EFI_NO_MEDIA if there is no media in the device.
  656. EFI_MEDIA_CHANGED if the media ID does not match the current device.
  657. EFI_BAD_BUFFER_SIZE if the buffer was not a multiple of the device block
  658. size.
  659. EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid,
  660. or the buffer is not properly aligned.
  661. --*/
  662. {
  663. UINT64 Offset;
  664. PEFI_PARTITION_DATA Private;
  665. EFI_STATUS Status;
  666. Private = EFI_PARTITION_DATA_FROM_THIS(This);
  667. ASSERT(Private->Magic == EFI_PARTITION_DATA_MAGIC);
  668. if ((BufferSize % Private->BlockSize) != 0) {
  669. Status = EfipPartitionProbeMediaStatus(Private->ParentDiskIo,
  670. MediaId,
  671. EFI_BAD_BUFFER_SIZE);
  672. return Status;
  673. }
  674. Offset = Lba * Private->BlockSize + Private->Start;
  675. if (Offset + BufferSize > Private->End) {
  676. Status = EfipPartitionProbeMediaStatus(Private->ParentDiskIo,
  677. MediaId,
  678. EFI_INVALID_PARAMETER);
  679. }
  680. //
  681. // Use the disk I/O protocol because some kinds of partitions have
  682. // different block sizes than their parents.
  683. //
  684. Status = Private->ParentDiskIo->WriteDisk(Private->ParentDiskIo,
  685. MediaId,
  686. Offset,
  687. BufferSize,
  688. Buffer);
  689. return Status;
  690. }
  691. EFIAPI
  692. EFI_STATUS
  693. EfiPartitionFlushBlocks (
  694. EFI_BLOCK_IO_PROTOCOL *This
  695. )
  696. /*++
  697. Routine Description:
  698. This routine flushes the block device.
  699. Arguments:
  700. This - Supplies a pointer to the protocol instance.
  701. Return Value:
  702. EFI_SUCCESS on success.
  703. EFI_DEVICE_ERROR if the device had an error and could not complete the
  704. request.
  705. EFI_NO_MEDIA if there is no media in the device.
  706. --*/
  707. {
  708. PEFI_PARTITION_DATA Private;
  709. EFI_STATUS Status;
  710. Private = EFI_PARTITION_DATA_FROM_THIS(This);
  711. ASSERT(Private->Magic == EFI_PARTITION_DATA_MAGIC);
  712. Status = Private->ParentBlockIo->FlushBlocks(Private->ParentBlockIo);
  713. return Status;
  714. }
  715. EFI_STATUS
  716. EfipPartitionProbeMediaStatus (
  717. EFI_DISK_IO_PROTOCOL *DiskIo,
  718. UINT32 MediaId,
  719. EFI_STATUS DefaultStatus
  720. )
  721. /*++
  722. Routine Description:
  723. This routine probes the media status and returns EFI_NO_MEDIA or
  724. EFI_MEDIA_CHANGED if the media changed. Otherwise a default status is
  725. returned.
  726. Arguments:
  727. DiskIo - Supplies a pointer to the disk I/O protocol.
  728. MediaId - Supplies the ID of the media, which changes every time the media
  729. is replaced.
  730. DefaultStatus - Supplies the status to return if a media event did not
  731. occur.
  732. Return Value:
  733. EFI_NO_MEDIA if there is no media.
  734. EFI_MEDIA_CHANGED if the media changed.
  735. Returns the default status parameter otherwise.
  736. --*/
  737. {
  738. EFI_STATUS Status;
  739. Status = DiskIo->ReadDisk(DiskIo, MediaId, 0, 1, NULL);
  740. if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
  741. return Status;
  742. }
  743. return DefaultStatus;
  744. }