1 /** @file
2   Partition driver that produces logical BlockIo devices from a physical
3   BlockIo device. The logical BlockIo devices are based on the format
4   of the raw block devices media. Currently "El Torito CD-ROM", Legacy
5   MBR, and GPT partition schemes are supported.
6 
7 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution.  The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12 
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 
16 **/
17 
18 
19 #include "Partition.h"
20 
21 //
22 // Partition Driver Global Variables.
23 //
24 EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = {
25   PartitionDriverBindingSupported,
26   PartitionDriverBindingStart,
27   PartitionDriverBindingStop,
28   //
29   // Grub4Dos copies the BPB of the first partition to the MBR. If the
30   // DriverBindingStart() of the Fat driver gets run before that of Partition
31   // driver only the first partition can be recognized.
32   // Let the driver binding version of Partition driver be higher than that of
33   // Fat driver to make sure the DriverBindingStart() of the Partition driver
34   // gets run before that of Fat driver so that all the partitions can be recognized.
35   //
36   0xb,
37   NULL,
38   NULL
39 };
40 
41 //
42 // Prioritized function list to detect partition table.
43 //
44 PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {
45   PartitionInstallGptChildHandles,
46   PartitionInstallElToritoChildHandles,
47   PartitionInstallMbrChildHandles,
48   NULL
49 };
50 
51 /**
52   Test to see if this driver supports ControllerHandle. Any ControllerHandle
53   than contains a BlockIo and DiskIo protocol or a BlockIo2 protocol can be
54   supported.
55 
56   @param[in]  This                Protocol instance pointer.
57   @param[in]  ControllerHandle    Handle of device to test.
58   @param[in]  RemainingDevicePath Optional parameter use to pick a specific child
59                                   device to start.
60 
61   @retval EFI_SUCCESS         This driver supports this device
62   @retval EFI_ALREADY_STARTED This driver is already running on this device
63   @retval other               This driver does not support this device
64 
65 **/
66 EFI_STATUS
67 EFIAPI
PartitionDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)68 PartitionDriverBindingSupported (
69   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
70   IN EFI_HANDLE                   ControllerHandle,
71   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
72   )
73 {
74   EFI_STATUS                Status;
75   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
76   EFI_DISK_IO_PROTOCOL      *DiskIo;
77   EFI_DEV_PATH              *Node;
78 
79   //
80   // Check RemainingDevicePath validation
81   //
82   if (RemainingDevicePath != NULL) {
83     //
84     // Check if RemainingDevicePath is the End of Device Path Node,
85     // if yes, go on checking other conditions
86     //
87     if (!IsDevicePathEnd (RemainingDevicePath)) {
88       //
89       // If RemainingDevicePath isn't the End of Device Path Node,
90       // check its validation
91       //
92       Node = (EFI_DEV_PATH *) RemainingDevicePath;
93       if (Node->DevPath.Type != MEDIA_DEVICE_PATH ||
94         Node->DevPath.SubType != MEDIA_HARDDRIVE_DP ||
95         DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH)) {
96         return EFI_UNSUPPORTED;
97       }
98     }
99   }
100 
101   //
102   // Open the IO Abstraction(s) needed to perform the supported test
103   //
104   Status = gBS->OpenProtocol (
105                   ControllerHandle,
106                   &gEfiDiskIoProtocolGuid,
107                   (VOID **) &DiskIo,
108                   This->DriverBindingHandle,
109                   ControllerHandle,
110                   EFI_OPEN_PROTOCOL_BY_DRIVER
111                   );
112   if (Status == EFI_ALREADY_STARTED) {
113     return EFI_SUCCESS;
114   }
115   if (EFI_ERROR (Status)) {
116     return Status;
117   }
118   //
119   // Close the I/O Abstraction(s) used to perform the supported test
120   //
121   gBS->CloseProtocol (
122          ControllerHandle,
123          &gEfiDiskIoProtocolGuid,
124          This->DriverBindingHandle,
125          ControllerHandle
126          );
127 
128   //
129   // Open the EFI Device Path protocol needed to perform the supported test
130   //
131   Status = gBS->OpenProtocol (
132                   ControllerHandle,
133                   &gEfiDevicePathProtocolGuid,
134                   (VOID **) &ParentDevicePath,
135                   This->DriverBindingHandle,
136                   ControllerHandle,
137                   EFI_OPEN_PROTOCOL_BY_DRIVER
138                   );
139   if (Status == EFI_ALREADY_STARTED) {
140     return EFI_SUCCESS;
141   }
142 
143   if (EFI_ERROR (Status)) {
144     return Status;
145   }
146 
147   //
148   // Close protocol, don't use device path protocol in the Support() function
149   //
150   gBS->CloseProtocol (
151         ControllerHandle,
152         &gEfiDevicePathProtocolGuid,
153         This->DriverBindingHandle,
154         ControllerHandle
155         );
156 
157   //
158   // Open the IO Abstraction(s) needed to perform the supported test
159   //
160   Status = gBS->OpenProtocol (
161                   ControllerHandle,
162                   &gEfiBlockIoProtocolGuid,
163                   NULL,
164                   This->DriverBindingHandle,
165                   ControllerHandle,
166                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
167                   );
168 
169   return Status;
170 }
171 
172 /**
173   Start this driver on ControllerHandle by opening a Block IO or a Block IO2
174   or both, and Disk IO protocol, reading Device Path, and creating a child
175   handle with a Disk IO and device path protocol.
176 
177   @param[in]  This                 Protocol instance pointer.
178   @param[in]  ControllerHandle     Handle of device to bind driver to
179   @param[in]  RemainingDevicePath  Optional parameter use to pick a specific child
180                                    device to start.
181 
182   @retval EFI_SUCCESS          This driver is added to ControllerHandle
183   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
184   @retval other                This driver does not support this device
185 
186 **/
187 EFI_STATUS
188 EFIAPI
PartitionDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)189 PartitionDriverBindingStart (
190   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
191   IN EFI_HANDLE                   ControllerHandle,
192   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
193   )
194 {
195   EFI_STATUS                Status;
196   EFI_STATUS                OpenStatus;
197   EFI_BLOCK_IO_PROTOCOL     *BlockIo;
198   EFI_BLOCK_IO2_PROTOCOL    *BlockIo2;
199   EFI_DISK_IO_PROTOCOL      *DiskIo;
200   EFI_DISK_IO2_PROTOCOL     *DiskIo2;
201   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
202   PARTITION_DETECT_ROUTINE  *Routine;
203   BOOLEAN                   MediaPresent;
204   EFI_TPL                   OldTpl;
205 
206   BlockIo2 = NULL;
207   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
208   //
209   // Check RemainingDevicePath validation
210   //
211   if (RemainingDevicePath != NULL) {
212     //
213     // Check if RemainingDevicePath is the End of Device Path Node,
214     // if yes, return EFI_SUCCESS
215     //
216     if (IsDevicePathEnd (RemainingDevicePath)) {
217       Status = EFI_SUCCESS;
218       goto Exit;
219     }
220   }
221 
222   //
223   // Try to open BlockIO and BlockIO2. If BlockIO would be opened, continue,
224   // otherwise, return error.
225   //
226   Status = gBS->OpenProtocol (
227                   ControllerHandle,
228                   &gEfiBlockIoProtocolGuid,
229                   (VOID **) &BlockIo,
230                   This->DriverBindingHandle,
231                   ControllerHandle,
232                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
233                   );
234   if (EFI_ERROR (Status)) {
235     goto Exit;
236   }
237 
238   Status = gBS->OpenProtocol (
239                   ControllerHandle,
240                   &gEfiBlockIo2ProtocolGuid,
241                   (VOID **) &BlockIo2,
242                   This->DriverBindingHandle,
243                   ControllerHandle,
244                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
245                   );
246   if (EFI_ERROR (Status)) {
247     BlockIo2 = NULL;
248   }
249 
250   //
251   // Get the Device Path Protocol on ControllerHandle's handle.
252   //
253   Status = gBS->OpenProtocol (
254                   ControllerHandle,
255                   &gEfiDevicePathProtocolGuid,
256                   (VOID **) &ParentDevicePath,
257                   This->DriverBindingHandle,
258                   ControllerHandle,
259                   EFI_OPEN_PROTOCOL_BY_DRIVER
260                   );
261   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
262     goto Exit;
263   }
264 
265   //
266   // Get the DiskIo and DiskIo2.
267   //
268   Status = gBS->OpenProtocol (
269                   ControllerHandle,
270                   &gEfiDiskIoProtocolGuid,
271                   (VOID **) &DiskIo,
272                   This->DriverBindingHandle,
273                   ControllerHandle,
274                   EFI_OPEN_PROTOCOL_BY_DRIVER
275                   );
276   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
277     gBS->CloseProtocol (
278           ControllerHandle,
279           &gEfiDevicePathProtocolGuid,
280           This->DriverBindingHandle,
281           ControllerHandle
282           );
283     goto Exit;
284   }
285 
286   OpenStatus = Status;
287 
288   Status = gBS->OpenProtocol (
289                   ControllerHandle,
290                   &gEfiDiskIo2ProtocolGuid,
291                   (VOID **) &DiskIo2,
292                   This->DriverBindingHandle,
293                   ControllerHandle,
294                   EFI_OPEN_PROTOCOL_BY_DRIVER
295                   );
296   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
297     DiskIo2 = NULL;
298   }
299 
300   //
301   // Try to read blocks when there's media or it is removable physical partition.
302   //
303   Status       = EFI_UNSUPPORTED;
304   MediaPresent = BlockIo->Media->MediaPresent;
305   if (BlockIo->Media->MediaPresent ||
306       (BlockIo->Media->RemovableMedia && !BlockIo->Media->LogicalPartition)) {
307     //
308     // Try for GPT, then El Torito, and then legacy MBR partition types. If the
309     // media supports a given partition type install child handles to represent
310     // the partitions described by the media.
311     //
312     Routine = &mPartitionDetectRoutineTable[0];
313     while (*Routine != NULL) {
314       Status = (*Routine) (
315                    This,
316                    ControllerHandle,
317                    DiskIo,
318                    DiskIo2,
319                    BlockIo,
320                    BlockIo2,
321                    ParentDevicePath
322                    );
323       if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED || Status == EFI_NO_MEDIA) {
324         break;
325       }
326       Routine++;
327     }
328   }
329   //
330   // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED),
331   // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the
332   // driver. So don't try to close them. Otherwise, we will break the dependency
333   // between the controller and the driver set up before.
334   //
335   // In the case that when the media changes on a device it will Reinstall the
336   // BlockIo interaface. This will cause a call to our Stop(), and a subsequent
337   // reentrant call to our Start() successfully. We should leave the device open
338   // when this happen. The "media change" case includes either the status is
339   // EFI_MEDIA_CHANGED or it is a "media" to "no media" change.
340   //
341   if (EFI_ERROR (Status)          &&
342       !EFI_ERROR (OpenStatus)     &&
343       Status != EFI_MEDIA_CHANGED &&
344       !(MediaPresent && Status == EFI_NO_MEDIA)) {
345     gBS->CloseProtocol (
346           ControllerHandle,
347           &gEfiDiskIoProtocolGuid,
348           This->DriverBindingHandle,
349           ControllerHandle
350           );
351     //
352     // Close Parent DiskIo2 if has.
353     //
354     gBS->CloseProtocol (
355            ControllerHandle,
356            &gEfiDiskIo2ProtocolGuid,
357            This->DriverBindingHandle,
358            ControllerHandle
359            );
360 
361     gBS->CloseProtocol (
362           ControllerHandle,
363           &gEfiDevicePathProtocolGuid,
364           This->DriverBindingHandle,
365           ControllerHandle
366           );
367   }
368 
369 Exit:
370   gBS->RestoreTPL (OldTpl);
371   return Status;
372 }
373 
374 /**
375   Stop this driver on ControllerHandle. Support stopping any child handles
376   created by this driver.
377 
378   @param  This              Protocol instance pointer.
379   @param  ControllerHandle  Handle of device to stop driver on
380   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
381                             children is zero stop the entire bus driver.
382   @param  ChildHandleBuffer List of Child Handles to Stop.
383 
384   @retval EFI_SUCCESS       This driver is removed ControllerHandle
385   @retval other             This driver was not removed from this device
386 
387 **/
388 EFI_STATUS
389 EFIAPI
PartitionDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)390 PartitionDriverBindingStop (
391   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
392   IN  EFI_HANDLE                    ControllerHandle,
393   IN  UINTN                         NumberOfChildren,
394   IN  EFI_HANDLE                    *ChildHandleBuffer
395   )
396 {
397   EFI_STATUS              Status;
398   UINTN                   Index;
399   EFI_BLOCK_IO_PROTOCOL   *BlockIo;
400   EFI_BLOCK_IO2_PROTOCOL  *BlockIo2;
401   BOOLEAN                 AllChildrenStopped;
402   PARTITION_PRIVATE_DATA  *Private;
403   EFI_DISK_IO_PROTOCOL    *DiskIo;
404 
405   BlockIo  = NULL;
406   BlockIo2 = NULL;
407   Private = NULL;
408 
409   if (NumberOfChildren == 0) {
410     //
411     // Close the bus driver
412     //
413     gBS->CloseProtocol (
414           ControllerHandle,
415           &gEfiDiskIoProtocolGuid,
416           This->DriverBindingHandle,
417           ControllerHandle
418           );
419     //
420     // Close Parent BlockIO2 if has.
421     //
422     gBS->CloseProtocol (
423            ControllerHandle,
424            &gEfiDiskIo2ProtocolGuid,
425            This->DriverBindingHandle,
426            ControllerHandle
427            );
428 
429     gBS->CloseProtocol (
430           ControllerHandle,
431           &gEfiDevicePathProtocolGuid,
432           This->DriverBindingHandle,
433           ControllerHandle
434           );
435     return EFI_SUCCESS;
436   }
437 
438   AllChildrenStopped = TRUE;
439   for (Index = 0; Index < NumberOfChildren; Index++) {
440     gBS->OpenProtocol (
441            ChildHandleBuffer[Index],
442            &gEfiBlockIoProtocolGuid,
443            (VOID **) &BlockIo,
444            This->DriverBindingHandle,
445            ControllerHandle,
446            EFI_OPEN_PROTOCOL_GET_PROTOCOL
447            );
448     //
449     // Try to locate BlockIo2.
450     //
451     gBS->OpenProtocol (
452            ChildHandleBuffer[Index],
453            &gEfiBlockIo2ProtocolGuid,
454            (VOID **) &BlockIo2,
455            This->DriverBindingHandle,
456            ControllerHandle,
457            EFI_OPEN_PROTOCOL_GET_PROTOCOL
458            );
459 
460 
461     Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);
462 
463     Status = gBS->CloseProtocol (
464                     ControllerHandle,
465                     &gEfiDiskIoProtocolGuid,
466                     This->DriverBindingHandle,
467                     ChildHandleBuffer[Index]
468                     );
469     //
470     // All Software protocols have be freed from the handle so remove it.
471     // Remove the BlockIo Protocol if has.
472     // Remove the BlockIo2 Protocol if has.
473     //
474     if (BlockIo2 != NULL) {
475       BlockIo->FlushBlocks (BlockIo);
476       BlockIo2->FlushBlocksEx (BlockIo2, NULL);
477       Status = gBS->UninstallMultipleProtocolInterfaces (
478                        ChildHandleBuffer[Index],
479                        &gEfiDevicePathProtocolGuid,
480                        Private->DevicePath,
481                        &gEfiBlockIoProtocolGuid,
482                        &Private->BlockIo,
483                        &gEfiBlockIo2ProtocolGuid,
484                        &Private->BlockIo2,
485                        Private->EspGuid,
486                        NULL,
487                        NULL
488                        );
489     } else {
490       BlockIo->FlushBlocks (BlockIo);
491       Status = gBS->UninstallMultipleProtocolInterfaces (
492                        ChildHandleBuffer[Index],
493                        &gEfiDevicePathProtocolGuid,
494                        Private->DevicePath,
495                        &gEfiBlockIoProtocolGuid,
496                        &Private->BlockIo,
497                        Private->EspGuid,
498                        NULL,
499                        NULL
500                        );
501     }
502 
503     if (EFI_ERROR (Status)) {
504       gBS->OpenProtocol (
505              ControllerHandle,
506              &gEfiDiskIoProtocolGuid,
507              (VOID **) &DiskIo,
508              This->DriverBindingHandle,
509              ChildHandleBuffer[Index],
510              EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
511              );
512     } else {
513       FreePool (Private->DevicePath);
514       FreePool (Private);
515     }
516 
517     if (EFI_ERROR (Status)) {
518       AllChildrenStopped = FALSE;
519     }
520   }
521 
522   if (!AllChildrenStopped) {
523     return EFI_DEVICE_ERROR;
524   }
525 
526   return EFI_SUCCESS;
527 }
528 
529 
530 /**
531   Reset the Block Device.
532 
533   @param  This                 Protocol instance pointer.
534   @param  ExtendedVerification Driver may perform diagnostics on reset.
535 
536   @retval EFI_SUCCESS          The device was reset.
537   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
538                                not be reset.
539 
540 **/
541 EFI_STATUS
542 EFIAPI
PartitionReset(IN EFI_BLOCK_IO_PROTOCOL * This,IN BOOLEAN ExtendedVerification)543 PartitionReset (
544   IN EFI_BLOCK_IO_PROTOCOL  *This,
545   IN BOOLEAN                ExtendedVerification
546   )
547 {
548   PARTITION_PRIVATE_DATA  *Private;
549 
550   Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
551 
552   return Private->ParentBlockIo->Reset (
553                                   Private->ParentBlockIo,
554                                   ExtendedVerification
555                                   );
556 }
557 
558 /**
559   Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED
560   for no media or media change case. Otherwise DefaultStatus is returned.
561 
562   @param DiskIo             Pointer to the DiskIo instance.
563   @param MediaId            Id of the media, changes every time the media is replaced.
564   @param DefaultStatus      The default status to return when it's not the no media
565                             or media change case.
566 
567   @retval EFI_NO_MEDIA      There is no media.
568   @retval EFI_MEDIA_CHANGED The media was changed.
569   @retval others            The default status to return.
570 **/
571 EFI_STATUS
ProbeMediaStatus(IN EFI_DISK_IO_PROTOCOL * DiskIo,IN UINT32 MediaId,IN EFI_STATUS DefaultStatus)572 ProbeMediaStatus (
573   IN EFI_DISK_IO_PROTOCOL    *DiskIo,
574   IN UINT32                  MediaId,
575   IN EFI_STATUS              DefaultStatus
576   )
577 {
578   EFI_STATUS                 Status;
579   UINT8                      Buffer[1];
580 
581   //
582   // Read 1 byte from offset 0 to check if the MediaId is still valid.
583   // The reading operation is synchronious thus it is not worth it to
584   // allocate a buffer from the pool. The destination buffer for the
585   // data is in the stack.
586   //
587   Status = DiskIo->ReadDisk (DiskIo, MediaId, 0, 1, (VOID*)Buffer);
588   if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
589     return Status;
590   }
591   return DefaultStatus;
592 }
593 
594 /**
595   Read by using the Disk IO protocol on the parent device. Lba addresses
596   must be converted to byte offsets.
597 
598   @param  This       Protocol instance pointer.
599   @param  MediaId    Id of the media, changes every time the media is replaced.
600   @param  Lba        The starting Logical Block Address to read from
601   @param  BufferSize Size of Buffer, must be a multiple of device block size.
602   @param  Buffer     Buffer containing read data
603 
604   @retval EFI_SUCCESS           The data was read correctly from the device.
605   @retval EFI_DEVICE_ERROR      The device reported an error while performing the read.
606   @retval EFI_NO_MEDIA          There is no media in the device.
607   @retval EFI_MEDIA_CHANGED     The MediaId does not matched the current device.
608   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
609   @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
610                                 valid for the device.
611 
612 **/
613 EFI_STATUS
614 EFIAPI
PartitionReadBlocks(IN EFI_BLOCK_IO_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN UINTN BufferSize,OUT VOID * Buffer)615 PartitionReadBlocks (
616   IN EFI_BLOCK_IO_PROTOCOL  *This,
617   IN UINT32                 MediaId,
618   IN EFI_LBA                Lba,
619   IN UINTN                  BufferSize,
620   OUT VOID                  *Buffer
621   )
622 {
623   PARTITION_PRIVATE_DATA  *Private;
624   UINT64                  Offset;
625 
626   Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
627 
628   if (BufferSize % Private->BlockSize != 0) {
629     return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
630   }
631 
632   Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
633   if (Offset + BufferSize > Private->End) {
634     return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
635   }
636   //
637   // Because some kinds of partition have different block size from their parent
638   // device, we call the Disk IO protocol on the parent device, not the Block IO
639   // protocol
640   //
641   return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
642 }
643 
644 /**
645   Write by using the Disk IO protocol on the parent device. Lba addresses
646   must be converted to byte offsets.
647 
648   @param[in]  This       Protocol instance pointer.
649   @param[in]  MediaId    Id of the media, changes every time the media is replaced.
650   @param[in]  Lba        The starting Logical Block Address to read from
651   @param[in]  BufferSize Size of Buffer, must be a multiple of device block size.
652   @param[in]  Buffer     Buffer containing data to be written to device.
653 
654   @retval EFI_SUCCESS           The data was written correctly to the device.
655   @retval EFI_WRITE_PROTECTED   The device can not be written to.
656   @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.
657   @retval EFI_NO_MEDIA          There is no media in the device.
658   @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
659   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
660   @retval EFI_INVALID_PARAMETER The write request contains a LBA that is not
661                                 valid for the device.
662 
663 **/
664 EFI_STATUS
665 EFIAPI
PartitionWriteBlocks(IN EFI_BLOCK_IO_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN UINTN BufferSize,IN VOID * Buffer)666 PartitionWriteBlocks (
667   IN EFI_BLOCK_IO_PROTOCOL  *This,
668   IN UINT32                 MediaId,
669   IN EFI_LBA                Lba,
670   IN UINTN                  BufferSize,
671   IN VOID                  *Buffer
672   )
673 {
674   PARTITION_PRIVATE_DATA  *Private;
675   UINT64                  Offset;
676 
677   Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
678 
679   if (BufferSize % Private->BlockSize != 0) {
680     return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
681   }
682 
683   Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
684   if (Offset + BufferSize > Private->End) {
685     return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
686   }
687   //
688   // Because some kinds of partition have different block size from their parent
689   // device, we call the Disk IO protocol on the parent device, not the Block IO
690   // protocol
691   //
692   return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
693 }
694 
695 
696 /**
697   Flush the parent Block Device.
698 
699   @param  This              Protocol instance pointer.
700 
701   @retval EFI_SUCCESS       All outstanding data was written to the device
702   @retval EFI_DEVICE_ERROR  The device reported an error while writting back the data
703   @retval EFI_NO_MEDIA      There is no media in the device.
704 
705 **/
706 EFI_STATUS
707 EFIAPI
PartitionFlushBlocks(IN EFI_BLOCK_IO_PROTOCOL * This)708 PartitionFlushBlocks (
709   IN EFI_BLOCK_IO_PROTOCOL  *This
710   )
711 {
712   PARTITION_PRIVATE_DATA  *Private;
713 
714   Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
715 
716   return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);
717 }
718 
719 /**
720   Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED
721   for no media or media change case. Otherwise DefaultStatus is returned.
722 
723   @param DiskIo2            Pointer to the DiskIo2 instance.
724   @param MediaId            Id of the media, changes every time the media is replaced.
725   @param DefaultStatus      The default status to return when it's not the no media
726                             or media change case.
727 
728   @retval EFI_NO_MEDIA      There is no media.
729   @retval EFI_MEDIA_CHANGED The media was changed.
730   @retval others            The default status to return.
731 **/
732 EFI_STATUS
ProbeMediaStatusEx(IN EFI_DISK_IO2_PROTOCOL * DiskIo2,IN UINT32 MediaId,IN EFI_STATUS DefaultStatus)733 ProbeMediaStatusEx (
734   IN EFI_DISK_IO2_PROTOCOL   *DiskIo2,
735   IN UINT32                  MediaId,
736   IN EFI_STATUS              DefaultStatus
737   )
738 {
739   EFI_STATUS                 Status;
740 
741   //
742   // Read 1 byte from offset 0 but passing NULL as buffer pointer
743   //
744   Status = DiskIo2->ReadDiskEx (DiskIo2, MediaId, 0, NULL, 1, NULL);
745   if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
746     return Status;
747   }
748   return DefaultStatus;
749 }
750 
751 /**
752   Reset the Block Device throught Block I/O2 protocol.
753 
754   @param  This                 Protocol instance pointer.
755   @param  ExtendedVerification Driver may perform diagnostics on reset.
756 
757   @retval EFI_SUCCESS          The device was reset.
758   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
759                                not be reset.
760 
761 **/
762 EFI_STATUS
763 EFIAPI
PartitionResetEx(IN EFI_BLOCK_IO2_PROTOCOL * This,IN BOOLEAN ExtendedVerification)764 PartitionResetEx (
765   IN EFI_BLOCK_IO2_PROTOCOL *This,
766   IN BOOLEAN                ExtendedVerification
767   )
768 {
769   PARTITION_PRIVATE_DATA  *Private;
770 
771   Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
772 
773   return Private->ParentBlockIo2->Reset (
774                                     Private->ParentBlockIo2,
775                                     ExtendedVerification
776                                     );
777 }
778 
779 /**
780   The general callback for the DiskIo2 interfaces.
781   @param  Event                 Event whose notification function is being invoked.
782   @param  Context               The pointer to the notification function's context,
783                                 which points to the PARTITION_ACCESS_TASK instance.
784 **/
785 VOID
786 EFIAPI
PartitionOnAccessComplete(IN EFI_EVENT Event,IN VOID * Context)787 PartitionOnAccessComplete (
788   IN EFI_EVENT                 Event,
789   IN VOID                      *Context
790   )
791 {
792   PARTITION_ACCESS_TASK   *Task;
793 
794   Task = (PARTITION_ACCESS_TASK *) Context;
795 
796   gBS->CloseEvent (Event);
797 
798   Task->BlockIo2Token->TransactionStatus = Task->DiskIo2Token.TransactionStatus;
799   gBS->SignalEvent (Task->BlockIo2Token->Event);
800 
801   FreePool (Task);
802 }
803 
804 /**
805   Create a new PARTITION_ACCESS_TASK instance.
806 
807   @param  Token  Pointer to the EFI_BLOCK_IO2_TOKEN.
808 
809   @return Pointer to the created PARTITION_ACCESS_TASK instance or NULL upon failure.
810 **/
811 PARTITION_ACCESS_TASK *
PartitionCreateAccessTask(IN EFI_BLOCK_IO2_TOKEN * Token)812 PartitionCreateAccessTask (
813   IN EFI_BLOCK_IO2_TOKEN    *Token
814   )
815 {
816   EFI_STATUS                Status;
817   PARTITION_ACCESS_TASK     *Task;
818 
819   Task = AllocatePool (sizeof (*Task));
820   if (Task == NULL) {
821     return NULL;
822   }
823 
824   Status = gBS->CreateEvent (
825                   EVT_NOTIFY_SIGNAL,
826                   TPL_NOTIFY,
827                   PartitionOnAccessComplete,
828                   Task,
829                   &Task->DiskIo2Token.Event
830                   );
831   if (EFI_ERROR (Status)) {
832     FreePool (Task);
833     return NULL;
834   }
835 
836   Task->BlockIo2Token = Token;
837 
838   return Task;
839 }
840 
841 /**
842   Read BufferSize bytes from Lba into Buffer.
843 
844   This function reads the requested number of blocks from the device. All the
845   blocks are read, or an error is returned.
846   If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and
847   non-blocking I/O is being used, the Event associated with this request will
848   not be signaled.
849 
850   @param[in]       This       Indicates a pointer to the calling context.
851   @param[in]       MediaId    Id of the media, changes every time the media is
852                               replaced.
853   @param[in]       Lba        The starting Logical Block Address to read from.
854   @param[in, out]  Token	    A pointer to the token associated with the transaction.
855   @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.
856   @param[out]      Buffer     A pointer to the destination buffer for the data. The
857                               caller is responsible for either having implicit or
858                               explicit ownership of the buffer.
859 
860   @retval EFI_SUCCESS           The read request was queued if Token->Event is
861                                 not NULL.The data was read correctly from the
862                                 device if the Token->Event is NULL.
863   @retval EFI_DEVICE_ERROR      The device reported an error while performing
864                                 the read.
865   @retval EFI_NO_MEDIA          There is no media in the device.
866   @retval EFI_MEDIA_CHANGED     The MediaId is not for the current media.
867   @retval EFI_BAD_BUFFER_SIZE   The BufferSize parameter is not a multiple of the
868                                 intrinsic block size of the device.
869   @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
870                                 or the buffer is not on proper alignment.
871   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack
872                                 of resources.
873 **/
874 EFI_STATUS
875 EFIAPI
PartitionReadBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN OUT EFI_BLOCK_IO2_TOKEN * Token,IN UINTN BufferSize,OUT VOID * Buffer)876 PartitionReadBlocksEx (
877   IN     EFI_BLOCK_IO2_PROTOCOL *This,
878   IN     UINT32                 MediaId,
879   IN     EFI_LBA                Lba,
880   IN OUT EFI_BLOCK_IO2_TOKEN    *Token,
881   IN     UINTN                  BufferSize,
882   OUT    VOID                   *Buffer
883   )
884 {
885   EFI_STATUS              Status;
886   PARTITION_PRIVATE_DATA  *Private;
887   UINT64                  Offset;
888   PARTITION_ACCESS_TASK   *Task;
889 
890   Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
891 
892   if (BufferSize % Private->BlockSize != 0) {
893     return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);
894   }
895 
896   Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
897   if (Offset + BufferSize > Private->End) {
898     return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);
899   }
900 
901   if ((Token != NULL) && (Token->Event != NULL)) {
902     Task = PartitionCreateAccessTask (Token);
903     if (Task == NULL) {
904       return EFI_OUT_OF_RESOURCES;
905     }
906 
907     Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);
908     if (EFI_ERROR (Status)) {
909       gBS->CloseEvent (Task->DiskIo2Token.Event);
910       FreePool (Task);
911     }
912   } else {
913     Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);
914   }
915 
916   return Status;
917 }
918 
919 /**
920   Write BufferSize bytes from Lba into Buffer.
921 
922   This function writes the requested number of blocks to the device. All blocks
923   are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,
924   EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is
925   being used, the Event associated with this request will not be signaled.
926 
927   @param[in]       This       Indicates a pointer to the calling context.
928   @param[in]       MediaId    The media ID that the write request is for.
929   @param[in]       Lba        The starting logical block address to be written. The
930                               caller is responsible for writing to only legitimate
931                               locations.
932   @param[in, out]  Token      A pointer to the token associated with the transaction.
933   @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.
934   @param[in]       Buffer     A pointer to the source buffer for the data.
935 
936   @retval EFI_SUCCESS           The write request was queued if Event is not NULL.
937                                 The data was written correctly to the device if
938                                 the Event is NULL.
939   @retval EFI_WRITE_PROTECTED   The device can not be written to.
940   @retval EFI_NO_MEDIA          There is no media in the device.
941   @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
942   @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.
943   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
944   @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
945                                 or the buffer is not on proper alignment.
946   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack
947                                 of resources.
948 
949 **/
950 EFI_STATUS
951 EFIAPI
PartitionWriteBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN OUT EFI_BLOCK_IO2_TOKEN * Token,IN UINTN BufferSize,IN VOID * Buffer)952 PartitionWriteBlocksEx (
953   IN     EFI_BLOCK_IO2_PROTOCOL *This,
954   IN     UINT32                 MediaId,
955   IN     EFI_LBA                Lba,
956   IN OUT EFI_BLOCK_IO2_TOKEN    *Token,
957   IN     UINTN                  BufferSize,
958   IN     VOID                   *Buffer
959   )
960 {
961   EFI_STATUS              Status;
962   PARTITION_PRIVATE_DATA  *Private;
963   UINT64                  Offset;
964   PARTITION_ACCESS_TASK   *Task;
965 
966   Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
967 
968   if (BufferSize % Private->BlockSize != 0) {
969     return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);
970   }
971 
972   Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
973   if (Offset + BufferSize > Private->End) {
974     return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);
975   }
976 
977   if ((Token != NULL) && (Token->Event != NULL)) {
978     Task = PartitionCreateAccessTask (Token);
979     if (Task == NULL) {
980       return EFI_OUT_OF_RESOURCES;
981     }
982 
983     Status =  Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);
984     if (EFI_ERROR (Status)) {
985       gBS->CloseEvent (Task->DiskIo2Token.Event);
986       FreePool (Task);
987     }
988   } else {
989     Status = Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);
990   }
991   return Status;
992 }
993 
994 /**
995   Flush the Block Device.
996 
997   If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED
998   is returned and non-blocking I/O is being used, the Event associated with
999   this request will not be signaled.
1000 
1001   @param[in]      This     Indicates a pointer to the calling context.
1002   @param[in, out] Token    A pointer to the token associated with the transaction
1003 
1004   @retval EFI_SUCCESS          The flush request was queued if Event is not NULL.
1005                                All outstanding data was written correctly to the
1006                                device if the Event is NULL.
1007   @retval EFI_DEVICE_ERROR     The device reported an error while writting back
1008                                the data.
1009   @retval EFI_WRITE_PROTECTED  The device cannot be written to.
1010   @retval EFI_NO_MEDIA         There is no media in the device.
1011   @retval EFI_MEDIA_CHANGED    The MediaId is not for the current media.
1012   @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
1013                                of resources.
1014 
1015 **/
1016 EFI_STATUS
1017 EFIAPI
PartitionFlushBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL * This,IN OUT EFI_BLOCK_IO2_TOKEN * Token)1018 PartitionFlushBlocksEx (
1019   IN     EFI_BLOCK_IO2_PROTOCOL *This,
1020   IN OUT EFI_BLOCK_IO2_TOKEN    *Token
1021   )
1022 {
1023   EFI_STATUS              Status;
1024   PARTITION_PRIVATE_DATA  *Private;
1025   PARTITION_ACCESS_TASK   *Task;
1026 
1027   Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
1028 
1029   if ((Token != NULL) && (Token->Event != NULL)) {
1030     Task = PartitionCreateAccessTask (Token);
1031     if (Task == NULL) {
1032       return EFI_OUT_OF_RESOURCES;
1033     }
1034 
1035     Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, &Task->DiskIo2Token);
1036     if (EFI_ERROR (Status)) {
1037       gBS->CloseEvent (Task->DiskIo2Token.Event);
1038       FreePool (Task);
1039     }
1040   } else {
1041     Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, NULL);
1042   }
1043   return Status;
1044 }
1045 
1046 
1047 /**
1048   Create a child handle for a logical block device that represents the
1049   bytes Start to End of the Parent Block IO device.
1050 
1051   @param[in]  This              Protocol instance pointer.
1052   @param[in]  ParentHandle      Parent Handle for new child.
1053   @param[in]  ParentDiskIo      Parent DiskIo interface.
1054   @param[in]  ParentDiskIo2     Parent DiskIo2 interface.
1055   @param[in]  ParentBlockIo     Parent BlockIo interface.
1056   @param[in]  ParentBlockIo2    Parent BlockIo2 interface.
1057   @param[in]  ParentDevicePath  Parent Device Path.
1058   @param[in]  DevicePathNode    Child Device Path node.
1059   @param[in]  Start             Start Block.
1060   @param[in]  End               End Block.
1061   @param[in]  BlockSize         Child block size.
1062   @param[in]  InstallEspGuid    Flag to install EFI System Partition GUID on handle.
1063 
1064   @retval EFI_SUCCESS       A child handle was added.
1065   @retval other             A child handle was not added.
1066 
1067 **/
1068 EFI_STATUS
PartitionInstallChildHandle(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ParentHandle,IN EFI_DISK_IO_PROTOCOL * ParentDiskIo,IN EFI_DISK_IO2_PROTOCOL * ParentDiskIo2,IN EFI_BLOCK_IO_PROTOCOL * ParentBlockIo,IN EFI_BLOCK_IO2_PROTOCOL * ParentBlockIo2,IN EFI_DEVICE_PATH_PROTOCOL * ParentDevicePath,IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN EFI_LBA Start,IN EFI_LBA End,IN UINT32 BlockSize,IN BOOLEAN InstallEspGuid)1069 PartitionInstallChildHandle (
1070   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
1071   IN  EFI_HANDLE                   ParentHandle,
1072   IN  EFI_DISK_IO_PROTOCOL         *ParentDiskIo,
1073   IN  EFI_DISK_IO2_PROTOCOL        *ParentDiskIo2,
1074   IN  EFI_BLOCK_IO_PROTOCOL        *ParentBlockIo,
1075   IN  EFI_BLOCK_IO2_PROTOCOL       *ParentBlockIo2,
1076   IN  EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath,
1077   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
1078   IN  EFI_LBA                      Start,
1079   IN  EFI_LBA                      End,
1080   IN  UINT32                       BlockSize,
1081   IN  BOOLEAN                      InstallEspGuid
1082   )
1083 {
1084   EFI_STATUS              Status;
1085   PARTITION_PRIVATE_DATA  *Private;
1086 
1087   Status  = EFI_SUCCESS;
1088   Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));
1089   if (Private == NULL) {
1090     return EFI_OUT_OF_RESOURCES;
1091   }
1092 
1093   Private->Signature        = PARTITION_PRIVATE_DATA_SIGNATURE;
1094 
1095   Private->Start            = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);
1096   Private->End              = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);
1097 
1098   Private->BlockSize        = BlockSize;
1099   Private->ParentBlockIo    = ParentBlockIo;
1100   Private->ParentBlockIo2   = ParentBlockIo2;
1101   Private->DiskIo           = ParentDiskIo;
1102   Private->DiskIo2          = ParentDiskIo2;
1103 
1104   //
1105   // Set the BlockIO into Private Data.
1106   //
1107   Private->BlockIo.Revision = ParentBlockIo->Revision;
1108 
1109   Private->BlockIo.Media    = &Private->Media;
1110   CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));
1111 
1112   Private->BlockIo.Reset        = PartitionReset;
1113   Private->BlockIo.ReadBlocks   = PartitionReadBlocks;
1114   Private->BlockIo.WriteBlocks  = PartitionWriteBlocks;
1115   Private->BlockIo.FlushBlocks  = PartitionFlushBlocks;
1116 
1117   //
1118   // Set the BlockIO2 into Private Data.
1119   //
1120   if (Private->DiskIo2 != NULL) {
1121     ASSERT (Private->ParentBlockIo2 != NULL);
1122     Private->BlockIo2.Media    = &Private->Media2;
1123     CopyMem (Private->BlockIo2.Media, ParentBlockIo2->Media, sizeof (EFI_BLOCK_IO_MEDIA));
1124 
1125     Private->BlockIo2.Reset          = PartitionResetEx;
1126     Private->BlockIo2.ReadBlocksEx   = PartitionReadBlocksEx;
1127     Private->BlockIo2.WriteBlocksEx  = PartitionWriteBlocksEx;
1128     Private->BlockIo2.FlushBlocksEx  = PartitionFlushBlocksEx;
1129   }
1130 
1131   Private->Media.IoAlign   = 0;
1132   Private->Media.LogicalPartition = TRUE;
1133   Private->Media.LastBlock = DivU64x32 (
1134                                MultU64x32 (
1135                                  End - Start + 1,
1136                                  ParentBlockIo->Media->BlockSize
1137                                  ),
1138                                 BlockSize
1139                                ) - 1;
1140 
1141   Private->Media.BlockSize = (UINT32) BlockSize;
1142 
1143   Private->Media2.IoAlign   = 0;
1144   Private->Media2.LogicalPartition = TRUE;
1145   Private->Media2.LastBlock = Private->Media.LastBlock;
1146   Private->Media2.BlockSize = (UINT32) BlockSize;
1147 
1148   //
1149   // Per UEFI Spec, LowestAlignedLba, LogicalBlocksPerPhysicalBlock and OptimalTransferLengthGranularity must be 0
1150   //  for logical partitions.
1151   //
1152   if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION2) {
1153     Private->Media.LowestAlignedLba               = 0;
1154     Private->Media.LogicalBlocksPerPhysicalBlock  = 0;
1155     Private->Media2.LowestAlignedLba              = 0;
1156     Private->Media2.LogicalBlocksPerPhysicalBlock = 0;
1157     if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION3) {
1158       Private->Media.OptimalTransferLengthGranularity  = 0;
1159       Private->Media2.OptimalTransferLengthGranularity = 0;
1160     }
1161   }
1162 
1163   Private->DevicePath     = AppendDevicePathNode (ParentDevicePath, DevicePathNode);
1164 
1165   if (Private->DevicePath == NULL) {
1166     FreePool (Private);
1167     return EFI_OUT_OF_RESOURCES;
1168   }
1169 
1170   if (InstallEspGuid) {
1171     Private->EspGuid = &gEfiPartTypeSystemPartGuid;
1172   } else {
1173     //
1174     // If NULL InstallMultipleProtocolInterfaces will ignore it.
1175     //
1176     Private->EspGuid = NULL;
1177   }
1178 
1179   //
1180   // Create the new handle.
1181   //
1182   Private->Handle = NULL;
1183   if (Private->DiskIo2 != NULL) {
1184     Status = gBS->InstallMultipleProtocolInterfaces (
1185                     &Private->Handle,
1186                     &gEfiDevicePathProtocolGuid,
1187                     Private->DevicePath,
1188                     &gEfiBlockIoProtocolGuid,
1189                     &Private->BlockIo,
1190                     &gEfiBlockIo2ProtocolGuid,
1191                     &Private->BlockIo2,
1192                     Private->EspGuid,
1193                     NULL,
1194                     NULL
1195                     );
1196   } else {
1197     Status = gBS->InstallMultipleProtocolInterfaces (
1198                     &Private->Handle,
1199                     &gEfiDevicePathProtocolGuid,
1200                     Private->DevicePath,
1201                     &gEfiBlockIoProtocolGuid,
1202                     &Private->BlockIo,
1203                     Private->EspGuid,
1204                     NULL,
1205                     NULL
1206                     );
1207   }
1208 
1209   if (!EFI_ERROR (Status)) {
1210     //
1211     // Open the Parent Handle for the child
1212     //
1213     Status = gBS->OpenProtocol (
1214                     ParentHandle,
1215                     &gEfiDiskIoProtocolGuid,
1216                     (VOID **) &ParentDiskIo,
1217                     This->DriverBindingHandle,
1218                     Private->Handle,
1219                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1220                     );
1221   } else {
1222     FreePool (Private->DevicePath);
1223     FreePool (Private);
1224   }
1225 
1226   return Status;
1227 }
1228 
1229 
1230 /**
1231   The user Entry Point for module Partition. The user code starts with this function.
1232 
1233   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
1234   @param[in] SystemTable    A pointer to the EFI System Table.
1235 
1236   @retval EFI_SUCCESS       The entry point is executed successfully.
1237   @retval other             Some error occurs when executing this entry point.
1238 
1239 **/
1240 EFI_STATUS
1241 EFIAPI
InitializePartition(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1242 InitializePartition (
1243   IN EFI_HANDLE           ImageHandle,
1244   IN EFI_SYSTEM_TABLE     *SystemTable
1245   )
1246 {
1247   EFI_STATUS              Status;
1248 
1249   //
1250   // Install driver model protocol(s).
1251   //
1252   Status = EfiLibInstallDriverBindingComponentName2 (
1253              ImageHandle,
1254              SystemTable,
1255              &gPartitionDriverBinding,
1256              ImageHandle,
1257              &gPartitionComponentName,
1258              &gPartitionComponentName2
1259              );
1260   ASSERT_EFI_ERROR (Status);
1261 
1262 
1263   return Status;
1264 }
1265 
1266