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", UDF, Legacy
5   MBR, and GPT partition schemes are supported.
6 
7 Copyright (c) 2018 Qualcomm Datacenter Technologies, Inc.
8 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
9 SPDX-License-Identifier: BSD-2-Clause-Patent
10 
11 **/
12 
13 #ifndef _PARTITION_H_
14 #define _PARTITION_H_
15 
16 #include <Uefi.h>
17 #include <Protocol/BlockIo.h>
18 #include <Protocol/BlockIo2.h>
19 #include <Guid/Gpt.h>
20 #include <Protocol/ComponentName.h>
21 #include <Protocol/DevicePath.h>
22 #include <Protocol/DriverBinding.h>
23 #include <Protocol/DiskIo.h>
24 #include <Protocol/DiskIo2.h>
25 #include <Protocol/PartitionInfo.h>
26 #include <Library/DebugLib.h>
27 #include <Library/UefiDriverEntryPoint.h>
28 #include <Library/BaseLib.h>
29 #include <Library/UefiLib.h>
30 #include <Library/BaseMemoryLib.h>
31 #include <Library/MemoryAllocationLib.h>
32 #include <Library/UefiBootServicesTableLib.h>
33 #include <Library/DevicePathLib.h>
34 
35 #include <IndustryStandard/Mbr.h>
36 #include <IndustryStandard/ElTorito.h>
37 #include <IndustryStandard/Udf.h>
38 
39 //
40 // Partition private data
41 //
42 #define PARTITION_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('P', 'a', 'r', 't')
43 typedef struct {
44   UINT64                       Signature;
45 
46   EFI_HANDLE                   Handle;
47   EFI_DEVICE_PATH_PROTOCOL     *DevicePath;
48   EFI_BLOCK_IO_PROTOCOL        BlockIo;
49   EFI_BLOCK_IO2_PROTOCOL       BlockIo2;
50   EFI_BLOCK_IO_MEDIA           Media;
51   EFI_BLOCK_IO_MEDIA           Media2;//For BlockIO2
52   EFI_PARTITION_INFO_PROTOCOL  PartitionInfo;
53 
54   EFI_DISK_IO_PROTOCOL         *DiskIo;
55   EFI_DISK_IO2_PROTOCOL        *DiskIo2;
56   EFI_BLOCK_IO_PROTOCOL        *ParentBlockIo;
57   EFI_BLOCK_IO2_PROTOCOL       *ParentBlockIo2;
58   UINT64                       Start;
59   UINT64                       End;
60   UINT32                       BlockSize;
61   BOOLEAN                      InStop;
62 
63   EFI_GUID                     TypeGuid;
64 
65 } PARTITION_PRIVATE_DATA;
66 
67 typedef struct {
68   EFI_DISK_IO2_TOKEN           DiskIo2Token;
69   EFI_BLOCK_IO2_TOKEN          *BlockIo2Token;
70 } PARTITION_ACCESS_TASK;
71 
72 #define PARTITION_DEVICE_FROM_BLOCK_IO_THIS(a)  CR (a, PARTITION_PRIVATE_DATA, BlockIo, PARTITION_PRIVATE_DATA_SIGNATURE)
73 #define PARTITION_DEVICE_FROM_BLOCK_IO2_THIS(a) CR (a, PARTITION_PRIVATE_DATA, BlockIo2, PARTITION_PRIVATE_DATA_SIGNATURE)
74 
75 //
76 // Global Variables
77 //
78 extern EFI_DRIVER_BINDING_PROTOCOL   gPartitionDriverBinding;
79 extern EFI_COMPONENT_NAME_PROTOCOL   gPartitionComponentName;
80 extern EFI_COMPONENT_NAME2_PROTOCOL  gPartitionComponentName2;
81 
82 //
83 // Extract INT32 from char array
84 //
85 #define UNPACK_INT32(a) (INT32)( (((UINT8 *) a)[0] <<  0) |    \
86                                  (((UINT8 *) a)[1] <<  8) |    \
87                                  (((UINT8 *) a)[2] << 16) |    \
88                                  (((UINT8 *) a)[3] << 24) )
89 
90 //
91 // Extract UINT32 from char array
92 //
93 #define UNPACK_UINT32(a) (UINT32)( (((UINT8 *) a)[0] <<  0) |    \
94                                    (((UINT8 *) a)[1] <<  8) |    \
95                                    (((UINT8 *) a)[2] << 16) |    \
96                                    (((UINT8 *) a)[3] << 24) )
97 
98 
99 //
100 // GPT Partition Entry Status
101 //
102 typedef struct {
103   BOOLEAN OutOfRange;
104   BOOLEAN Overlap;
105   BOOLEAN OsSpecific;
106 } EFI_PARTITION_ENTRY_STATUS;
107 
108 //
109 // Function Prototypes
110 //
111 /**
112   Test to see if this driver supports ControllerHandle. Any ControllerHandle
113   than contains a BlockIo and DiskIo protocol can be supported.
114 
115   @param  This                Protocol instance pointer.
116   @param  ControllerHandle    Handle of device to test
117   @param  RemainingDevicePath Optional parameter use to pick a specific child
118                               device to start.
119 
120   @retval EFI_SUCCESS         This driver supports this device
121   @retval EFI_ALREADY_STARTED This driver is already running on this device
122   @retval other               This driver does not support this device
123 
124 **/
125 EFI_STATUS
126 EFIAPI
127 PartitionDriverBindingSupported (
128   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
129   IN EFI_HANDLE                   ControllerHandle,
130   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
131   );
132 
133 /**
134   Start this driver on ControllerHandle by opening a Block IO and Disk IO
135   protocol, reading Device Path, and creating a child handle with a
136   Disk IO and device path protocol.
137 
138   @param  This                 Protocol instance pointer.
139   @param  ControllerHandle     Handle of device to bind driver to
140   @param  RemainingDevicePath  Optional parameter use to pick a specific child
141                                device to start.
142 
143   @retval EFI_SUCCESS          This driver is added to ControllerHandle
144   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
145   @retval other                This driver does not support this device
146 
147 **/
148 EFI_STATUS
149 EFIAPI
150 PartitionDriverBindingStart (
151   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
152   IN EFI_HANDLE                   ControllerHandle,
153   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
154   );
155 
156 /**
157   Stop this driver on ControllerHandle. Support stopping any child handles
158   created by this driver.
159 
160   @param  This              Protocol instance pointer.
161   @param  ControllerHandle  Handle of device to stop driver on
162   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
163                             children is zero stop the entire bus driver.
164   @param  ChildHandleBuffer List of Child Handles to Stop.
165 
166   @retval EFI_SUCCESS       This driver is removed ControllerHandle
167   @retval other             This driver was not removed from this device
168 
169 **/
170 EFI_STATUS
171 EFIAPI
172 PartitionDriverBindingStop (
173   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
174   IN  EFI_HANDLE                    ControllerHandle,
175   IN  UINTN                         NumberOfChildren,
176   IN  EFI_HANDLE                    *ChildHandleBuffer
177   );
178 
179 //
180 // EFI Component Name Functions
181 //
182 /**
183   Retrieves a Unicode string that is the user readable name of the driver.
184 
185   This function retrieves the user readable name of a driver in the form of a
186   Unicode string. If the driver specified by This has a user readable name in
187   the language specified by Language, then a pointer to the driver name is
188   returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
189   by This does not support the language specified by Language,
190   then EFI_UNSUPPORTED is returned.
191 
192   @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
193                                 EFI_COMPONENT_NAME_PROTOCOL instance.
194 
195   @param  Language[in]          A pointer to a Null-terminated ASCII string
196                                 array indicating the language. This is the
197                                 language of the driver name that the caller is
198                                 requesting, and it must match one of the
199                                 languages specified in SupportedLanguages. The
200                                 number of languages supported by a driver is up
201                                 to the driver writer. Language is specified
202                                 in RFC 4646 or ISO 639-2 language code format.
203 
204   @param  DriverName[out]       A pointer to the Unicode string to return.
205                                 This Unicode string is the name of the
206                                 driver specified by This in the language
207                                 specified by Language.
208 
209   @retval EFI_SUCCESS           The Unicode string for the Driver specified by
210                                 This and the language specified by Language was
211                                 returned in DriverName.
212 
213   @retval EFI_INVALID_PARAMETER Language is NULL.
214 
215   @retval EFI_INVALID_PARAMETER DriverName is NULL.
216 
217   @retval EFI_UNSUPPORTED       The driver specified by This does not support
218                                 the language specified by Language.
219 
220 **/
221 EFI_STATUS
222 EFIAPI
223 PartitionComponentNameGetDriverName (
224   IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
225   IN  CHAR8                        *Language,
226   OUT CHAR16                       **DriverName
227   );
228 
229 
230 /**
231   Retrieves a Unicode string that is the user readable name of the controller
232   that is being managed by a driver.
233 
234   This function retrieves the user readable name of the controller specified by
235   ControllerHandle and ChildHandle in the form of a Unicode string. If the
236   driver specified by This has a user readable name in the language specified by
237   Language, then a pointer to the controller name is returned in ControllerName,
238   and EFI_SUCCESS is returned.  If the driver specified by This is not currently
239   managing the controller specified by ControllerHandle and ChildHandle,
240   then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
241   support the language specified by Language, then EFI_UNSUPPORTED is returned.
242 
243   @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
244                                 EFI_COMPONENT_NAME_PROTOCOL instance.
245 
246   @param  ControllerHandle[in]  The handle of a controller that the driver
247                                 specified by This is managing.  This handle
248                                 specifies the controller whose name is to be
249                                 returned.
250 
251   @param  ChildHandle[in]       The handle of the child controller to retrieve
252                                 the name of.  This is an optional parameter that
253                                 may be NULL.  It will be NULL for device
254                                 drivers.  It will also be NULL for a bus drivers
255                                 that wish to retrieve the name of the bus
256                                 controller.  It will not be NULL for a bus
257                                 driver that wishes to retrieve the name of a
258                                 child controller.
259 
260   @param  Language[in]          A pointer to a Null-terminated ASCII string
261                                 array indicating the language.  This is the
262                                 language of the driver name that the caller is
263                                 requesting, and it must match one of the
264                                 languages specified in SupportedLanguages. The
265                                 number of languages supported by a driver is up
266                                 to the driver writer. Language is specified in
267                                 RFC 4646 or ISO 639-2 language code format.
268 
269   @param  ControllerName[out]   A pointer to the Unicode string to return.
270                                 This Unicode string is the name of the
271                                 controller specified by ControllerHandle and
272                                 ChildHandle in the language specified by
273                                 Language from the point of view of the driver
274                                 specified by This.
275 
276   @retval EFI_SUCCESS           The Unicode string for the user readable name in
277                                 the language specified by Language for the
278                                 driver specified by This was returned in
279                                 DriverName.
280 
281   @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
282 
283   @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
284                                 EFI_HANDLE.
285 
286   @retval EFI_INVALID_PARAMETER Language is NULL.
287 
288   @retval EFI_INVALID_PARAMETER ControllerName is NULL.
289 
290   @retval EFI_UNSUPPORTED       The driver specified by This is not currently
291                                 managing the controller specified by
292                                 ControllerHandle and ChildHandle.
293 
294   @retval EFI_UNSUPPORTED       The driver specified by This does not support
295                                 the language specified by Language.
296 
297 **/
298 EFI_STATUS
299 EFIAPI
300 PartitionComponentNameGetControllerName (
301   IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
302   IN  EFI_HANDLE                                      ControllerHandle,
303   IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
304   IN  CHAR8                                           *Language,
305   OUT CHAR16                                          **ControllerName
306   );
307 
308 
309 /**
310   Create a child handle for a logical block device that represents the
311   bytes Start to End of the Parent Block IO device.
312 
313   @param[in]  This              Protocol instance pointer.
314   @param[in]  ParentHandle      Parent Handle for new child.
315   @param[in]  ParentDiskIo      Parent DiskIo interface.
316   @param[in]  ParentDiskIo2     Parent DiskIo2 interface.
317   @param[in]  ParentBlockIo     Parent BlockIo interface.
318   @param[in]  ParentBlockIo2    Parent BlockIo2 interface.
319   @param[in]  ParentDevicePath  Parent Device Path.
320   @param[in]  DevicePathNode    Child Device Path node.
321   @param[in]  PartitionInfo     Child Partition Information interface.
322   @param[in]  Start             Start Block.
323   @param[in]  End               End Block.
324   @param[in]  BlockSize         Child block size.
325   @param[in]  TypeGuid          Parition Type Guid.
326 
327   @retval EFI_SUCCESS       A child handle was added.
328   @retval other             A child handle was not added.
329 
330 **/
331 EFI_STATUS
332 PartitionInstallChildHandle (
333   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
334   IN  EFI_HANDLE                   ParentHandle,
335   IN  EFI_DISK_IO_PROTOCOL         *ParentDiskIo,
336   IN  EFI_DISK_IO2_PROTOCOL        *ParentDiskIo2,
337   IN  EFI_BLOCK_IO_PROTOCOL        *ParentBlockIo,
338   IN  EFI_BLOCK_IO2_PROTOCOL       *ParentBlockIo2,
339   IN  EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath,
340   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
341   IN  EFI_PARTITION_INFO_PROTOCOL  *PartitionInfo,
342   IN  EFI_LBA                      Start,
343   IN  EFI_LBA                      End,
344   IN  UINT32                       BlockSize,
345   IN  EFI_GUID                     *TypeGuid
346   );
347 
348 /**
349   Test to see if there is any child on ControllerHandle.
350 
351   @param[in]  ControllerHandle    Handle of device to test.
352 
353   @retval TRUE                    There are children on the ControllerHandle.
354   @retval FALSE                   No child is on the ControllerHandle.
355 
356 **/
357 BOOLEAN
358 HasChildren (
359   IN EFI_HANDLE           ControllerHandle
360   );
361 
362 /**
363   Install child handles if the Handle supports GPT partition structure.
364 
365   @param[in]  This       Calling context.
366   @param[in]  Handle     Parent Handle.
367   @param[in]  DiskIo     Parent DiskIo interface.
368   @param[in]  DiskIo2    Parent DiskIo2 interface.
369   @param[in]  BlockIo    Parent BlockIo interface.
370   @param[in]  BlockIo2   Parent BlockIo2 interface.
371   @param[in]  DevicePath Parent Device Path.
372 
373   @retval EFI_SUCCESS           Valid GPT disk.
374   @retval EFI_MEDIA_CHANGED     Media changed Detected.
375   @retval EFI_INVALID_PARAMETER If both BlockIo and BlockIo2 are NULL;
376   @retval other                 Not a valid GPT disk.
377 
378 **/
379 EFI_STATUS
380 PartitionInstallGptChildHandles (
381   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
382   IN  EFI_HANDLE                   Handle,
383   IN  EFI_DISK_IO_PROTOCOL         *DiskIo,
384   IN  EFI_DISK_IO2_PROTOCOL        *DiskIo2,
385   IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,
386   IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,
387   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
388   );
389 
390 /**
391   Install child handles if the Handle supports El Torito format.
392 
393   @param[in]  This        Calling context.
394   @param[in]  Handle      Parent Handle.
395   @param[in]  DiskIo      Parent DiskIo interface.
396   @param[in]  DiskIo2     Parent DiskIo2 interface.
397   @param[in]  BlockIo     Parent BlockIo interface.
398   @param[in]  BlockIo2    Parent BlockIo2 interface.
399   @param[in]  DevicePath  Parent Device Path
400 
401 
402   @retval EFI_SUCCESS         Child handle(s) was added.
403   @retval EFI_MEDIA_CHANGED   Media changed Detected.
404   @retval other               no child handle was added.
405 
406 **/
407 EFI_STATUS
408 PartitionInstallElToritoChildHandles (
409   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
410   IN  EFI_HANDLE                   Handle,
411   IN  EFI_DISK_IO_PROTOCOL         *DiskIo,
412   IN  EFI_DISK_IO2_PROTOCOL        *DiskIo2,
413   IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,
414   IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,
415   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
416   );
417 
418 /**
419   Install child handles if the Handle supports MBR format.
420 
421   @param[in]  This              Calling context.
422   @param[in]  Handle            Parent Handle.
423   @param[in]  DiskIo            Parent DiskIo interface.
424   @param[in]  DiskIo2           Parent DiskIo2 interface.
425   @param[in]  BlockIo           Parent BlockIo interface.
426   @param[in]  BlockIo2          Parent BlockIo2 interface.
427   @param[in]  DevicePath        Parent Device Path.
428 
429   @retval EFI_SUCCESS       A child handle was added.
430   @retval EFI_MEDIA_CHANGED Media change was detected.
431   @retval Others            MBR partition was not found.
432 
433 **/
434 EFI_STATUS
435 PartitionInstallMbrChildHandles (
436   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
437   IN  EFI_HANDLE                   Handle,
438   IN  EFI_DISK_IO_PROTOCOL         *DiskIo,
439   IN  EFI_DISK_IO2_PROTOCOL        *DiskIo2,
440   IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,
441   IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,
442   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
443   );
444 
445 /**
446   Install child handles if the Handle supports UDF/ECMA-167 volume format.
447 
448   @param[in]  This        Calling context.
449   @param[in]  Handle      Parent Handle.
450   @param[in]  DiskIo      Parent DiskIo interface.
451   @param[in]  DiskIo2     Parent DiskIo2 interface.
452   @param[in]  BlockIo     Parent BlockIo interface.
453   @param[in]  BlockIo2    Parent BlockIo2 interface.
454   @param[in]  DevicePath  Parent Device Path
455 
456 
457   @retval EFI_SUCCESS         Child handle(s) was added.
458   @retval EFI_MEDIA_CHANGED   Media changed Detected.
459   @retval other               no child handle was added.
460 
461 **/
462 EFI_STATUS
463 PartitionInstallUdfChildHandles (
464   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
465   IN  EFI_HANDLE                   Handle,
466   IN  EFI_DISK_IO_PROTOCOL         *DiskIo,
467   IN  EFI_DISK_IO2_PROTOCOL        *DiskIo2,
468   IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,
469   IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,
470   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
471   );
472 
473 typedef
474 EFI_STATUS
475 (*PARTITION_DETECT_ROUTINE) (
476   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
477   IN  EFI_HANDLE                   Handle,
478   IN  EFI_DISK_IO_PROTOCOL         *DiskIo,
479   IN  EFI_DISK_IO2_PROTOCOL        *DiskIo2,
480   IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,
481   IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,
482   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
483   );
484 
485 #endif
486