]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
Libraries and utilities for instrumenting regions of code and measuring their perform...
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / PartitionDxe / Partition.c
CommitLineData
adbcbf8f 1/** @file\r
2 Partition driver that produces logical BlockIo devices from a physical\r
3 BlockIo device. The logical BlockIo devices are based on the format\r
4 of the raw block devices media. Currently "El Torito CD-ROM", Legacy\r
5 MBR, and GPT partition schemes are supported.\r
6\r
9afd0514 7Copyright (c) 2006 - 2009, Intel Corporation. <BR>\r
f42be642 8All rights reserved. This program and the accompanying materials\r
9are licensed and made available under the terms and conditions of the BSD License\r
10which accompanies this distribution. The full text of the license may be found at\r
11http://opensource.org/licenses/bsd-license.php\r
adbcbf8f 12\r
f42be642 13THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
adbcbf8f 15\r
16**/\r
17\r
18\r
19#include "Partition.h"\r
20\r
21//\r
ff61847d 22// Partition Driver Global Variables.\r
adbcbf8f 23//\r
24EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = {\r
25 PartitionDriverBindingSupported,\r
26 PartitionDriverBindingStart,\r
27 PartitionDriverBindingStop,\r
28 0xa,\r
29 NULL,\r
30 NULL\r
31};\r
32\r
ff61847d 33//\r
48557c65 34// Prioritized function list to detect partition table. \r
ff61847d 35//\r
adbcbf8f 36PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {\r
37 PartitionInstallGptChildHandles,\r
38 PartitionInstallElToritoChildHandles,\r
39 PartitionInstallMbrChildHandles,\r
40 NULL\r
41};\r
42\r
43\r
44\r
45/**\r
46 Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
47 than contains a BlockIo and DiskIo protocol can be supported.\r
48\r
49 @param This Protocol instance pointer.\r
50 @param ControllerHandle Handle of device to test\r
51 @param RemainingDevicePath Optional parameter use to pick a specific child\r
52 device to start.\r
53\r
54 @retval EFI_SUCCESS This driver supports this device\r
55 @retval EFI_ALREADY_STARTED This driver is already running on this device\r
56 @retval other This driver does not support this device\r
57\r
58**/\r
59EFI_STATUS\r
60EFIAPI\r
61PartitionDriverBindingSupported (\r
62 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
63 IN EFI_HANDLE ControllerHandle,\r
64 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
65 )\r
66{\r
67 EFI_STATUS Status;\r
68 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
69 EFI_DISK_IO_PROTOCOL *DiskIo;\r
70 EFI_DEV_PATH *Node;\r
71\r
9be29006 72 //\r
73 // Check RemainingDevicePath validation\r
74 //\r
adbcbf8f 75 if (RemainingDevicePath != NULL) {\r
9be29006 76 //\r
77 // Check if RemainingDevicePath is the End of Device Path Node, \r
78 // if yes, go on checking other conditions\r
79 //\r
80 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
81 //\r
82 // If RemainingDevicePath isn't the End of Device Path Node,\r
83 // check its validation\r
84 //\r
85 Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
86 if (Node->DevPath.Type != MEDIA_DEVICE_PATH ||\r
adbcbf8f 87 Node->DevPath.SubType != MEDIA_HARDDRIVE_DP ||\r
9be29006 88 DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH)) {\r
adbcbf8f 89 return EFI_UNSUPPORTED;\r
9be29006 90 }\r
adbcbf8f 91 }\r
92 }\r
9be29006 93\r
adbcbf8f 94 //\r
95 // Open the IO Abstraction(s) needed to perform the supported test\r
96 //\r
97 Status = gBS->OpenProtocol (\r
98 ControllerHandle,\r
9be29006 99 &gEfiDiskIoProtocolGuid,\r
100 (VOID **) &DiskIo,\r
adbcbf8f 101 This->DriverBindingHandle,\r
102 ControllerHandle,\r
103 EFI_OPEN_PROTOCOL_BY_DRIVER\r
104 );\r
105 if (Status == EFI_ALREADY_STARTED) {\r
106 return EFI_SUCCESS;\r
107 }\r
108\r
109 if (EFI_ERROR (Status)) {\r
110 return Status;\r
111 }\r
112 //\r
113 // Close the I/O Abstraction(s) used to perform the supported test\r
114 //\r
115 gBS->CloseProtocol (\r
ff61847d 116 ControllerHandle,\r
9be29006 117 &gEfiDiskIoProtocolGuid,\r
ff61847d 118 This->DriverBindingHandle,\r
119 ControllerHandle\r
120 );\r
adbcbf8f 121\r
122 //\r
9be29006 123 // Open the EFI Device Path protocol needed to perform the supported test\r
adbcbf8f 124 //\r
125 Status = gBS->OpenProtocol (\r
126 ControllerHandle,\r
9be29006 127 &gEfiDevicePathProtocolGuid,\r
128 (VOID **) &ParentDevicePath,\r
adbcbf8f 129 This->DriverBindingHandle,\r
130 ControllerHandle,\r
131 EFI_OPEN_PROTOCOL_BY_DRIVER\r
132 );\r
133 if (Status == EFI_ALREADY_STARTED) {\r
134 return EFI_SUCCESS;\r
135 }\r
136\r
137 if (EFI_ERROR (Status)) {\r
138 return Status;\r
139 }\r
9be29006 140\r
adbcbf8f 141 //\r
9be29006 142 // Close protocol, don't use device path protocol in the Support() function\r
adbcbf8f 143 //\r
144 gBS->CloseProtocol (\r
145 ControllerHandle,\r
9be29006 146 &gEfiDevicePathProtocolGuid,\r
adbcbf8f 147 This->DriverBindingHandle,\r
148 ControllerHandle\r
149 );\r
150\r
151 //\r
152 // Open the IO Abstraction(s) needed to perform the supported test\r
153 //\r
154 Status = gBS->OpenProtocol (\r
155 ControllerHandle,\r
156 &gEfiBlockIoProtocolGuid,\r
157 NULL,\r
158 This->DriverBindingHandle,\r
159 ControllerHandle,\r
160 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
161 );\r
162\r
163 return Status;\r
164}\r
165\r
166\r
167/**\r
168 Start this driver on ControllerHandle by opening a Block IO and Disk IO\r
169 protocol, reading Device Path, and creating a child handle with a\r
170 Disk IO and device path protocol.\r
171\r
172 @param This Protocol instance pointer.\r
173 @param ControllerHandle Handle of device to bind driver to\r
174 @param RemainingDevicePath Optional parameter use to pick a specific child\r
175 device to start.\r
176\r
177 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
178 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
179 @retval other This driver does not support this device\r
180\r
181**/\r
182EFI_STATUS\r
183EFIAPI\r
184PartitionDriverBindingStart (\r
185 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
186 IN EFI_HANDLE ControllerHandle,\r
187 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
188 )\r
189{\r
190 EFI_STATUS Status;\r
191 EFI_STATUS OpenStatus;\r
192 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
193 EFI_DISK_IO_PROTOCOL *DiskIo;\r
194 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
195 PARTITION_DETECT_ROUTINE *Routine;\r
9afd0514 196 BOOLEAN MediaPresent;\r
adbcbf8f 197\r
9be29006 198 //\r
199 // Check RemainingDevicePath validation\r
200 //\r
201 if (RemainingDevicePath != NULL) {\r
202 //\r
203 // Check if RemainingDevicePath is the End of Device Path Node, \r
204 // if yes, return EFI_SUCCESS\r
205 //\r
206 if (IsDevicePathEnd (RemainingDevicePath)) {\r
207 return EFI_SUCCESS;\r
208 }\r
209 }\r
210\r
adbcbf8f 211 Status = gBS->OpenProtocol (\r
212 ControllerHandle,\r
213 &gEfiBlockIoProtocolGuid,\r
214 (VOID **) &BlockIo,\r
215 This->DriverBindingHandle,\r
216 ControllerHandle,\r
217 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
218 );\r
219 if (EFI_ERROR (Status)) {\r
220 return Status;\r
221 }\r
222 //\r
223 // Get the Device Path Protocol on ControllerHandle's handle\r
224 //\r
225 Status = gBS->OpenProtocol (\r
226 ControllerHandle,\r
227 &gEfiDevicePathProtocolGuid,\r
228 (VOID **) &ParentDevicePath,\r
229 This->DriverBindingHandle,\r
230 ControllerHandle,\r
231 EFI_OPEN_PROTOCOL_BY_DRIVER\r
232 );\r
233 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
234 return Status;\r
235 }\r
236\r
237 Status = gBS->OpenProtocol (\r
238 ControllerHandle,\r
239 &gEfiDiskIoProtocolGuid,\r
240 (VOID **) &DiskIo,\r
241 This->DriverBindingHandle,\r
242 ControllerHandle,\r
243 EFI_OPEN_PROTOCOL_BY_DRIVER\r
244 );\r
245 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
246 gBS->CloseProtocol (\r
247 ControllerHandle,\r
248 &gEfiDevicePathProtocolGuid,\r
249 This->DriverBindingHandle,\r
250 ControllerHandle\r
251 );\r
252 return Status;\r
253 }\r
254\r
255 OpenStatus = Status;\r
256\r
257 //\r
9afd0514 258 // Try to read blocks when there's media or it is removable physical partition.\r
adbcbf8f 259 //\r
9afd0514 260 Status = EFI_UNSUPPORTED;\r
261 MediaPresent = BlockIo->Media->MediaPresent;\r
262 if (BlockIo->Media->MediaPresent ||\r
263 (BlockIo->Media->RemovableMedia && !BlockIo->Media->LogicalPartition)) {\r
adbcbf8f 264 //\r
265 // Try for GPT, then El Torito, and then legacy MBR partition types. If the\r
266 // media supports a given partition type install child handles to represent\r
267 // the partitions described by the media.\r
268 //\r
269 Routine = &mPartitionDetectRoutineTable[0];\r
270 while (*Routine != NULL) {\r
271 Status = (*Routine) (\r
272 This,\r
273 ControllerHandle,\r
274 DiskIo,\r
275 BlockIo,\r
276 ParentDevicePath\r
277 );\r
9afd0514 278 if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED || Status == EFI_NO_MEDIA) {\r
adbcbf8f 279 break;\r
280 }\r
281 Routine++;\r
282 }\r
283 }\r
284 //\r
285 // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED),\r
286 // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the\r
287 // driver. So don't try to close them. Otherwise, we will break the dependency\r
288 // between the controller and the driver set up before.\r
289 //\r
9afd0514 290 // In the case that when the media changes on a device it will Reinstall the \r
291 // BlockIo interaface. This will cause a call to our Stop(), and a subsequent\r
292 // reentrant call to our Start() successfully. We should leave the device open\r
293 // when this happen. The "media change" case includes either the status is\r
294 // EFI_MEDIA_CHANGED or it is a "media" to "no media" change. \r
295 // \r
296 if (EFI_ERROR (Status) &&\r
297 !EFI_ERROR (OpenStatus) &&\r
298 Status != EFI_MEDIA_CHANGED &&\r
299 !(MediaPresent && Status == EFI_NO_MEDIA)) {\r
adbcbf8f 300 gBS->CloseProtocol (\r
301 ControllerHandle,\r
302 &gEfiDiskIoProtocolGuid,\r
303 This->DriverBindingHandle,\r
304 ControllerHandle\r
305 );\r
306\r
307 gBS->CloseProtocol (\r
308 ControllerHandle,\r
309 &gEfiDevicePathProtocolGuid,\r
310 This->DriverBindingHandle,\r
311 ControllerHandle\r
312 );\r
313 }\r
314\r
315 return Status;\r
316}\r
317\r
318\r
319/**\r
48557c65 320 Stop this driver on ControllerHandle. Support stopping any child handles\r
adbcbf8f 321 created by this driver.\r
322\r
323 @param This Protocol instance pointer.\r
324 @param ControllerHandle Handle of device to stop driver on\r
325 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
326 children is zero stop the entire bus driver.\r
327 @param ChildHandleBuffer List of Child Handles to Stop.\r
328\r
329 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
330 @retval other This driver was not removed from this device\r
331\r
332**/\r
333EFI_STATUS\r
334EFIAPI\r
335PartitionDriverBindingStop (\r
336 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
337 IN EFI_HANDLE ControllerHandle,\r
338 IN UINTN NumberOfChildren,\r
339 IN EFI_HANDLE *ChildHandleBuffer\r
340 )\r
341{\r
342 EFI_STATUS Status;\r
343 UINTN Index;\r
344 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
345 BOOLEAN AllChildrenStopped;\r
346 PARTITION_PRIVATE_DATA *Private;\r
347 EFI_DISK_IO_PROTOCOL *DiskIo;\r
348\r
349 if (NumberOfChildren == 0) {\r
350 //\r
351 // Close the bus driver\r
352 //\r
353 gBS->CloseProtocol (\r
354 ControllerHandle,\r
355 &gEfiDiskIoProtocolGuid,\r
356 This->DriverBindingHandle,\r
357 ControllerHandle\r
358 );\r
359\r
360 gBS->CloseProtocol (\r
361 ControllerHandle,\r
362 &gEfiDevicePathProtocolGuid,\r
363 This->DriverBindingHandle,\r
364 ControllerHandle\r
365 );\r
366\r
367 return EFI_SUCCESS;\r
368 }\r
369\r
370 AllChildrenStopped = TRUE;\r
371 for (Index = 0; Index < NumberOfChildren; Index++) {\r
372 Status = gBS->OpenProtocol (\r
373 ChildHandleBuffer[Index],\r
374 &gEfiBlockIoProtocolGuid,\r
375 (VOID **) &BlockIo,\r
376 This->DriverBindingHandle,\r
377 ControllerHandle,\r
378 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
379 );\r
380 if (!EFI_ERROR (Status)) {\r
381\r
382 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);\r
383\r
384 //\r
385 // All Software protocols have be freed from the handle so remove it.\r
386 //\r
387 BlockIo->FlushBlocks (BlockIo);\r
388\r
389 Status = gBS->CloseProtocol (\r
390 ControllerHandle,\r
391 &gEfiDiskIoProtocolGuid,\r
392 This->DriverBindingHandle,\r
393 ChildHandleBuffer[Index]\r
394 );\r
395\r
396 Status = gBS->UninstallMultipleProtocolInterfaces (\r
397 ChildHandleBuffer[Index],\r
398 &gEfiDevicePathProtocolGuid,\r
399 Private->DevicePath,\r
400 &gEfiBlockIoProtocolGuid,\r
401 &Private->BlockIo,\r
402 Private->EspGuid,\r
403 NULL,\r
404 NULL\r
405 );\r
406 if (EFI_ERROR (Status)) {\r
407 gBS->OpenProtocol (\r
408 ControllerHandle,\r
409 &gEfiDiskIoProtocolGuid,\r
410 (VOID **) &DiskIo,\r
411 This->DriverBindingHandle,\r
412 ChildHandleBuffer[Index],\r
413 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
414 );\r
415 } else {\r
416 FreePool (Private->DevicePath);\r
417 FreePool (Private);\r
418 }\r
419\r
420 }\r
421\r
422 if (EFI_ERROR (Status)) {\r
423 AllChildrenStopped = FALSE;\r
424 }\r
425 }\r
426\r
427 if (!AllChildrenStopped) {\r
428 return EFI_DEVICE_ERROR;\r
429 }\r
430\r
431 return EFI_SUCCESS;\r
432}\r
433\r
434\r
435/**\r
436 Reset the Block Device.\r
437\r
438 @param This Protocol instance pointer.\r
439 @param ExtendedVerification Driver may perform diagnostics on reset.\r
440\r
441 @retval EFI_SUCCESS The device was reset.\r
442 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
443 not be reset.\r
444\r
445**/\r
adbcbf8f 446EFI_STATUS\r
447EFIAPI\r
448PartitionReset (\r
449 IN EFI_BLOCK_IO_PROTOCOL *This,\r
450 IN BOOLEAN ExtendedVerification\r
451 )\r
452{\r
453 PARTITION_PRIVATE_DATA *Private;\r
454\r
455 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
456\r
457 return Private->ParentBlockIo->Reset (\r
458 Private->ParentBlockIo,\r
459 ExtendedVerification\r
460 );\r
461}\r
462\r
463\r
464/**\r
465 Read by using the Disk IO protocol on the parent device. Lba addresses\r
466 must be converted to byte offsets.\r
467\r
468 @param This Protocol instance pointer.\r
469 @param MediaId Id of the media, changes every time the media is replaced.\r
470 @param Lba The starting Logical Block Address to read from\r
471 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
472 @param Buffer Buffer containing read data\r
473\r
474 @retval EFI_SUCCESS The data was read correctly from the device.\r
475 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
476 @retval EFI_NO_MEDIA There is no media in the device.\r
477 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
478 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
479 @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not\r
480 valid for the device.\r
481\r
482**/\r
adbcbf8f 483EFI_STATUS\r
484EFIAPI\r
485PartitionReadBlocks (\r
486 IN EFI_BLOCK_IO_PROTOCOL *This,\r
487 IN UINT32 MediaId,\r
488 IN EFI_LBA Lba,\r
489 IN UINTN BufferSize,\r
490 OUT VOID *Buffer\r
491 )\r
492{\r
493 PARTITION_PRIVATE_DATA *Private;\r
494 UINT64 Offset;\r
495\r
496 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
497\r
498 if (BufferSize % Private->BlockSize != 0) {\r
499 return EFI_BAD_BUFFER_SIZE;\r
500 }\r
501\r
502 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
503 if (Offset + BufferSize > Private->End) {\r
504 return EFI_INVALID_PARAMETER;\r
505 }\r
506 //\r
507 // Because some kinds of partition have different block size from their parent\r
508 // device, we call the Disk IO protocol on the parent device, not the Block IO\r
509 // protocol\r
510 //\r
511 return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);\r
512}\r
513\r
514/**\r
515 Write by using the Disk IO protocol on the parent device. Lba addresses\r
516 must be converted to byte offsets.\r
517\r
518 @param This Protocol instance pointer.\r
519 @param MediaId Id of the media, changes every time the media is replaced.\r
520 @param Lba The starting Logical Block Address to read from\r
521 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
522 @param Buffer Buffer containing read data\r
523\r
524 @retval EFI_SUCCESS The data was written correctly to the device.\r
525 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
526 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
527 @retval EFI_NO_MEDIA There is no media in the device.\r
528 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
529 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
530 @retval EFI_INVALID_PARAMETER The write request contains a LBA that is not\r
531 valid for the device.\r
532\r
533**/\r
adbcbf8f 534EFI_STATUS\r
535EFIAPI\r
536PartitionWriteBlocks (\r
537 IN EFI_BLOCK_IO_PROTOCOL *This,\r
538 IN UINT32 MediaId,\r
539 IN EFI_LBA Lba,\r
540 IN UINTN BufferSize,\r
541 OUT VOID *Buffer\r
542 )\r
543{\r
544 PARTITION_PRIVATE_DATA *Private;\r
545 UINT64 Offset;\r
546\r
547 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
548\r
549 if (BufferSize % Private->BlockSize != 0) {\r
550 return EFI_BAD_BUFFER_SIZE;\r
551 }\r
552\r
553 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
554 if (Offset + BufferSize > Private->End) {\r
555 return EFI_INVALID_PARAMETER;\r
556 }\r
557 //\r
558 // Because some kinds of partition have different block size from their parent\r
559 // device, we call the Disk IO protocol on the parent device, not the Block IO\r
560 // protocol\r
561 //\r
562 return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);\r
563}\r
564\r
565\r
566/**\r
567 Flush the parent Block Device.\r
568\r
569 @param This Protocol instance pointer.\r
570\r
571 @retval EFI_SUCCESS All outstanding data was written to the device\r
572 @retval EFI_DEVICE_ERROR The device reported an error while writting back the data\r
573 @retval EFI_NO_MEDIA There is no media in the device.\r
574\r
575**/\r
adbcbf8f 576EFI_STATUS\r
577EFIAPI\r
578PartitionFlushBlocks (\r
579 IN EFI_BLOCK_IO_PROTOCOL *This\r
580 )\r
581{\r
582 PARTITION_PRIVATE_DATA *Private;\r
583\r
584 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
585\r
586 return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);\r
587}\r
588\r
589\r
590\r
591/**\r
592 Create a child handle for a logical block device that represents the\r
593 bytes Start to End of the Parent Block IO device.\r
594\r
a8d0c20e 595 @param[in] This Protocol instance pointer\r
adbcbf8f 596 @param[in] ParentHandle Parent Handle for new child\r
597 @param[in] ParentDiskIo Parent DiskIo interface\r
598 @param[in] ParentBlockIo Parent BlockIo interface\r
599 @param[in] ParentDevicePath Parent Device Path\r
600 @param[in] DevicePathNode Child Device Path node\r
601 @param[in] Start Start Block\r
602 @param[in] End End Block\r
603 @param[in] BlockSize Child block size\r
604 @param[in] InstallEspGuid Flag to install EFI System Partition GUID on handle\r
605\r
606 @retval EFI_SUCCESS A child handle was added\r
607 @retval other A child handle was not added\r
608\r
609**/\r
610EFI_STATUS\r
611PartitionInstallChildHandle (\r
612 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
613 IN EFI_HANDLE ParentHandle,\r
614 IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,\r
615 IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,\r
616 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
617 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,\r
618 IN EFI_LBA Start,\r
619 IN EFI_LBA End,\r
620 IN UINT32 BlockSize,\r
621 IN BOOLEAN InstallEspGuid\r
622 )\r
623{\r
624 EFI_STATUS Status;\r
625 PARTITION_PRIVATE_DATA *Private;\r
626\r
627 Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));\r
628 if (Private == NULL) {\r
629 return EFI_OUT_OF_RESOURCES;\r
630 }\r
631\r
632 Private->Signature = PARTITION_PRIVATE_DATA_SIGNATURE;\r
633\r
634 Private->Start = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);\r
635 Private->End = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);\r
636\r
637 Private->BlockSize = BlockSize;\r
638 Private->ParentBlockIo = ParentBlockIo;\r
639 Private->DiskIo = ParentDiskIo;\r
640\r
9e9f86ec 641 Private->BlockIo.Revision = ParentBlockIo->Revision;\r
adbcbf8f 642\r
643 Private->BlockIo.Media = &Private->Media;\r
f1e2b802 644 CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));\r
adbcbf8f 645 Private->Media.LogicalPartition = TRUE;\r
646 Private->Media.LastBlock = DivU64x32 (\r
647 MultU64x32 (\r
648 End - Start + 1,\r
649 ParentBlockIo->Media->BlockSize\r
650 ),\r
651 BlockSize\r
652 ) - 1;\r
653\r
654 Private->Media.BlockSize = (UINT32) BlockSize;\r
655\r
656 Private->BlockIo.Reset = PartitionReset;\r
657 Private->BlockIo.ReadBlocks = PartitionReadBlocks;\r
658 Private->BlockIo.WriteBlocks = PartitionWriteBlocks;\r
659 Private->BlockIo.FlushBlocks = PartitionFlushBlocks;\r
660\r
661 Private->DevicePath = AppendDevicePathNode (ParentDevicePath, DevicePathNode);\r
662\r
663 if (Private->DevicePath == NULL) {\r
664 FreePool (Private);\r
665 return EFI_OUT_OF_RESOURCES;\r
666 }\r
667\r
668 if (InstallEspGuid) {\r
669 Private->EspGuid = &gEfiPartTypeSystemPartGuid;\r
670 } else {\r
671 //\r
672 // If NULL InstallMultipleProtocolInterfaces will ignore it.\r
673 //\r
674 Private->EspGuid = NULL;\r
675 }\r
676 //\r
677 // Create the new handle\r
678 //\r
679 Private->Handle = NULL;\r
680 Status = gBS->InstallMultipleProtocolInterfaces (\r
681 &Private->Handle,\r
682 &gEfiDevicePathProtocolGuid,\r
683 Private->DevicePath,\r
684 &gEfiBlockIoProtocolGuid,\r
685 &Private->BlockIo,\r
686 Private->EspGuid,\r
687 NULL,\r
688 NULL\r
689 );\r
690\r
691 if (!EFI_ERROR (Status)) {\r
692 //\r
693 // Open the Parent Handle for the child\r
694 //\r
695 Status = gBS->OpenProtocol (\r
696 ParentHandle,\r
697 &gEfiDiskIoProtocolGuid,\r
698 (VOID **) &ParentDiskIo,\r
699 This->DriverBindingHandle,\r
700 Private->Handle,\r
701 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
702 );\r
703 } else {\r
704 FreePool (Private->DevicePath);\r
705 FreePool (Private);\r
706 }\r
707\r
708 return Status;\r
709}\r
710\r
711\r
712/**\r
713 The user Entry Point for module Partition. The user code starts with this function.\r
714\r
715 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
716 @param[in] SystemTable A pointer to the EFI System Table.\r
717 \r
718 @retval EFI_SUCCESS The entry point is executed successfully.\r
719 @retval other Some error occurs when executing this entry point.\r
720\r
721**/\r
722EFI_STATUS\r
723EFIAPI\r
724InitializePartition (\r
725 IN EFI_HANDLE ImageHandle,\r
726 IN EFI_SYSTEM_TABLE *SystemTable\r
727 )\r
728{\r
729 EFI_STATUS Status;\r
730\r
731 //\r
732 // Install driver model protocol(s).\r
733 //\r
d38a0f44 734 Status = EfiLibInstallDriverBindingComponentName2 (\r
adbcbf8f 735 ImageHandle,\r
736 SystemTable,\r
737 &gPartitionDriverBinding,\r
738 ImageHandle,\r
739 &gPartitionComponentName,\r
d38a0f44 740 &gPartitionComponentName2\r
adbcbf8f 741 );\r
742 ASSERT_EFI_ERROR (Status);\r
743\r
744\r
745 return Status;\r
746}\r
747\r