]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
Refine code to make code run more safely.
[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
67f802ed 7Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 8This program and the accompanying materials\r
f42be642 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
15cc67e6 197 EFI_TPL OldTpl;\r
adbcbf8f 198\r
15cc67e6 199 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); \r
9be29006 200 //\r
201 // Check RemainingDevicePath validation\r
202 //\r
203 if (RemainingDevicePath != NULL) {\r
204 //\r
205 // Check if RemainingDevicePath is the End of Device Path Node, \r
206 // if yes, return EFI_SUCCESS\r
207 //\r
208 if (IsDevicePathEnd (RemainingDevicePath)) {\r
15cc67e6 209 Status = EFI_SUCCESS;\r
210 goto Exit;\r
9be29006 211 }\r
212 }\r
213\r
adbcbf8f 214 Status = gBS->OpenProtocol (\r
215 ControllerHandle,\r
216 &gEfiBlockIoProtocolGuid,\r
217 (VOID **) &BlockIo,\r
218 This->DriverBindingHandle,\r
219 ControllerHandle,\r
220 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
221 );\r
222 if (EFI_ERROR (Status)) {\r
15cc67e6 223 goto Exit;\r
adbcbf8f 224 }\r
225 //\r
226 // Get the Device Path Protocol on ControllerHandle's handle\r
227 //\r
228 Status = gBS->OpenProtocol (\r
229 ControllerHandle,\r
230 &gEfiDevicePathProtocolGuid,\r
231 (VOID **) &ParentDevicePath,\r
232 This->DriverBindingHandle,\r
233 ControllerHandle,\r
234 EFI_OPEN_PROTOCOL_BY_DRIVER\r
235 );\r
236 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
15cc67e6 237 goto Exit;\r
adbcbf8f 238 }\r
239\r
240 Status = gBS->OpenProtocol (\r
241 ControllerHandle,\r
242 &gEfiDiskIoProtocolGuid,\r
243 (VOID **) &DiskIo,\r
244 This->DriverBindingHandle,\r
245 ControllerHandle,\r
246 EFI_OPEN_PROTOCOL_BY_DRIVER\r
247 );\r
248 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
249 gBS->CloseProtocol (\r
250 ControllerHandle,\r
251 &gEfiDevicePathProtocolGuid,\r
252 This->DriverBindingHandle,\r
253 ControllerHandle\r
254 );\r
15cc67e6 255 goto Exit;\r
adbcbf8f 256 }\r
257\r
258 OpenStatus = Status;\r
259\r
260 //\r
9afd0514 261 // Try to read blocks when there's media or it is removable physical partition.\r
adbcbf8f 262 //\r
9afd0514 263 Status = EFI_UNSUPPORTED;\r
264 MediaPresent = BlockIo->Media->MediaPresent;\r
265 if (BlockIo->Media->MediaPresent ||\r
266 (BlockIo->Media->RemovableMedia && !BlockIo->Media->LogicalPartition)) {\r
adbcbf8f 267 //\r
268 // Try for GPT, then El Torito, and then legacy MBR partition types. If the\r
269 // media supports a given partition type install child handles to represent\r
270 // the partitions described by the media.\r
271 //\r
272 Routine = &mPartitionDetectRoutineTable[0];\r
273 while (*Routine != NULL) {\r
274 Status = (*Routine) (\r
275 This,\r
276 ControllerHandle,\r
277 DiskIo,\r
278 BlockIo,\r
279 ParentDevicePath\r
280 );\r
9afd0514 281 if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED || Status == EFI_NO_MEDIA) {\r
adbcbf8f 282 break;\r
283 }\r
284 Routine++;\r
285 }\r
286 }\r
287 //\r
288 // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED),\r
289 // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the\r
290 // driver. So don't try to close them. Otherwise, we will break the dependency\r
291 // between the controller and the driver set up before.\r
292 //\r
9afd0514 293 // In the case that when the media changes on a device it will Reinstall the \r
294 // BlockIo interaface. This will cause a call to our Stop(), and a subsequent\r
295 // reentrant call to our Start() successfully. We should leave the device open\r
296 // when this happen. The "media change" case includes either the status is\r
297 // EFI_MEDIA_CHANGED or it is a "media" to "no media" change. \r
298 // \r
299 if (EFI_ERROR (Status) &&\r
300 !EFI_ERROR (OpenStatus) &&\r
301 Status != EFI_MEDIA_CHANGED &&\r
302 !(MediaPresent && Status == EFI_NO_MEDIA)) {\r
adbcbf8f 303 gBS->CloseProtocol (\r
304 ControllerHandle,\r
305 &gEfiDiskIoProtocolGuid,\r
306 This->DriverBindingHandle,\r
307 ControllerHandle\r
308 );\r
309\r
310 gBS->CloseProtocol (\r
311 ControllerHandle,\r
312 &gEfiDevicePathProtocolGuid,\r
313 This->DriverBindingHandle,\r
314 ControllerHandle\r
315 );\r
316 }\r
317\r
15cc67e6 318Exit:\r
319 gBS->RestoreTPL (OldTpl);\r
adbcbf8f 320 return Status;\r
321}\r
322\r
323\r
324/**\r
48557c65 325 Stop this driver on ControllerHandle. Support stopping any child handles\r
adbcbf8f 326 created by this driver.\r
327\r
328 @param This Protocol instance pointer.\r
329 @param ControllerHandle Handle of device to stop driver on\r
330 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
331 children is zero stop the entire bus driver.\r
332 @param ChildHandleBuffer List of Child Handles to Stop.\r
333\r
334 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
335 @retval other This driver was not removed from this device\r
336\r
337**/\r
338EFI_STATUS\r
339EFIAPI\r
340PartitionDriverBindingStop (\r
341 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
342 IN EFI_HANDLE ControllerHandle,\r
343 IN UINTN NumberOfChildren,\r
344 IN EFI_HANDLE *ChildHandleBuffer\r
345 )\r
346{\r
347 EFI_STATUS Status;\r
348 UINTN Index;\r
349 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
350 BOOLEAN AllChildrenStopped;\r
351 PARTITION_PRIVATE_DATA *Private;\r
352 EFI_DISK_IO_PROTOCOL *DiskIo;\r
353\r
354 if (NumberOfChildren == 0) {\r
355 //\r
356 // Close the bus driver\r
357 //\r
358 gBS->CloseProtocol (\r
359 ControllerHandle,\r
360 &gEfiDiskIoProtocolGuid,\r
361 This->DriverBindingHandle,\r
362 ControllerHandle\r
363 );\r
364\r
365 gBS->CloseProtocol (\r
366 ControllerHandle,\r
367 &gEfiDevicePathProtocolGuid,\r
368 This->DriverBindingHandle,\r
369 ControllerHandle\r
370 );\r
371\r
372 return EFI_SUCCESS;\r
373 }\r
374\r
375 AllChildrenStopped = TRUE;\r
376 for (Index = 0; Index < NumberOfChildren; Index++) {\r
377 Status = gBS->OpenProtocol (\r
378 ChildHandleBuffer[Index],\r
379 &gEfiBlockIoProtocolGuid,\r
380 (VOID **) &BlockIo,\r
381 This->DriverBindingHandle,\r
382 ControllerHandle,\r
383 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
384 );\r
385 if (!EFI_ERROR (Status)) {\r
386\r
387 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);\r
388\r
389 //\r
390 // All Software protocols have be freed from the handle so remove it.\r
391 //\r
392 BlockIo->FlushBlocks (BlockIo);\r
393\r
394 Status = gBS->CloseProtocol (\r
395 ControllerHandle,\r
396 &gEfiDiskIoProtocolGuid,\r
397 This->DriverBindingHandle,\r
398 ChildHandleBuffer[Index]\r
399 );\r
400\r
401 Status = gBS->UninstallMultipleProtocolInterfaces (\r
402 ChildHandleBuffer[Index],\r
403 &gEfiDevicePathProtocolGuid,\r
404 Private->DevicePath,\r
405 &gEfiBlockIoProtocolGuid,\r
406 &Private->BlockIo,\r
407 Private->EspGuid,\r
408 NULL,\r
409 NULL\r
410 );\r
411 if (EFI_ERROR (Status)) {\r
412 gBS->OpenProtocol (\r
413 ControllerHandle,\r
414 &gEfiDiskIoProtocolGuid,\r
415 (VOID **) &DiskIo,\r
416 This->DriverBindingHandle,\r
417 ChildHandleBuffer[Index],\r
418 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
419 );\r
420 } else {\r
421 FreePool (Private->DevicePath);\r
422 FreePool (Private);\r
423 }\r
424\r
425 }\r
426\r
427 if (EFI_ERROR (Status)) {\r
428 AllChildrenStopped = FALSE;\r
429 }\r
430 }\r
431\r
432 if (!AllChildrenStopped) {\r
433 return EFI_DEVICE_ERROR;\r
434 }\r
435\r
436 return EFI_SUCCESS;\r
437}\r
438\r
439\r
440/**\r
441 Reset the Block Device.\r
442\r
443 @param This Protocol instance pointer.\r
444 @param ExtendedVerification Driver may perform diagnostics on reset.\r
445\r
446 @retval EFI_SUCCESS The device was reset.\r
447 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
448 not be reset.\r
449\r
450**/\r
adbcbf8f 451EFI_STATUS\r
452EFIAPI\r
453PartitionReset (\r
454 IN EFI_BLOCK_IO_PROTOCOL *This,\r
455 IN BOOLEAN ExtendedVerification\r
456 )\r
457{\r
458 PARTITION_PRIVATE_DATA *Private;\r
459\r
460 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
461\r
462 return Private->ParentBlockIo->Reset (\r
463 Private->ParentBlockIo,\r
464 ExtendedVerification\r
465 );\r
466}\r
467\r
468\r
469/**\r
470 Read by using the Disk IO protocol on the parent device. Lba addresses\r
471 must be converted to byte offsets.\r
472\r
473 @param This Protocol instance pointer.\r
474 @param MediaId Id of the media, changes every time the media is replaced.\r
475 @param Lba The starting Logical Block Address to read from\r
476 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
477 @param Buffer Buffer containing read data\r
478\r
479 @retval EFI_SUCCESS The data was read correctly from the device.\r
480 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
481 @retval EFI_NO_MEDIA There is no media in the device.\r
482 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
483 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
484 @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not\r
485 valid for the device.\r
486\r
487**/\r
adbcbf8f 488EFI_STATUS\r
489EFIAPI\r
490PartitionReadBlocks (\r
491 IN EFI_BLOCK_IO_PROTOCOL *This,\r
492 IN UINT32 MediaId,\r
493 IN EFI_LBA Lba,\r
494 IN UINTN BufferSize,\r
495 OUT VOID *Buffer\r
496 )\r
497{\r
498 PARTITION_PRIVATE_DATA *Private;\r
499 UINT64 Offset;\r
500\r
501 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
502\r
503 if (BufferSize % Private->BlockSize != 0) {\r
504 return EFI_BAD_BUFFER_SIZE;\r
505 }\r
506\r
507 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
508 if (Offset + BufferSize > Private->End) {\r
509 return EFI_INVALID_PARAMETER;\r
510 }\r
511 //\r
512 // Because some kinds of partition have different block size from their parent\r
513 // device, we call the Disk IO protocol on the parent device, not the Block IO\r
514 // protocol\r
515 //\r
516 return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);\r
517}\r
518\r
519/**\r
520 Write by using the Disk IO protocol on the parent device. Lba addresses\r
521 must be converted to byte offsets.\r
522\r
523 @param This Protocol instance pointer.\r
524 @param MediaId Id of the media, changes every time the media is replaced.\r
525 @param Lba The starting Logical Block Address to read from\r
526 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
527 @param Buffer Buffer containing read data\r
528\r
529 @retval EFI_SUCCESS The data was written correctly to the device.\r
530 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
531 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
532 @retval EFI_NO_MEDIA There is no media in the device.\r
533 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
534 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
535 @retval EFI_INVALID_PARAMETER The write request contains a LBA that is not\r
536 valid for the device.\r
537\r
538**/\r
adbcbf8f 539EFI_STATUS\r
540EFIAPI\r
541PartitionWriteBlocks (\r
542 IN EFI_BLOCK_IO_PROTOCOL *This,\r
543 IN UINT32 MediaId,\r
544 IN EFI_LBA Lba,\r
545 IN UINTN BufferSize,\r
546 OUT VOID *Buffer\r
547 )\r
548{\r
549 PARTITION_PRIVATE_DATA *Private;\r
550 UINT64 Offset;\r
551\r
552 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
553\r
554 if (BufferSize % Private->BlockSize != 0) {\r
555 return EFI_BAD_BUFFER_SIZE;\r
556 }\r
557\r
558 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
559 if (Offset + BufferSize > Private->End) {\r
560 return EFI_INVALID_PARAMETER;\r
561 }\r
562 //\r
563 // Because some kinds of partition have different block size from their parent\r
564 // device, we call the Disk IO protocol on the parent device, not the Block IO\r
565 // protocol\r
566 //\r
567 return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);\r
568}\r
569\r
570\r
571/**\r
572 Flush the parent Block Device.\r
573\r
574 @param This Protocol instance pointer.\r
575\r
576 @retval EFI_SUCCESS All outstanding data was written to the device\r
577 @retval EFI_DEVICE_ERROR The device reported an error while writting back the data\r
578 @retval EFI_NO_MEDIA There is no media in the device.\r
579\r
580**/\r
adbcbf8f 581EFI_STATUS\r
582EFIAPI\r
583PartitionFlushBlocks (\r
584 IN EFI_BLOCK_IO_PROTOCOL *This\r
585 )\r
586{\r
587 PARTITION_PRIVATE_DATA *Private;\r
588\r
589 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
590\r
591 return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);\r
592}\r
593\r
594\r
595\r
596/**\r
597 Create a child handle for a logical block device that represents the\r
598 bytes Start to End of the Parent Block IO device.\r
599\r
a8d0c20e 600 @param[in] This Protocol instance pointer\r
adbcbf8f 601 @param[in] ParentHandle Parent Handle for new child\r
602 @param[in] ParentDiskIo Parent DiskIo interface\r
603 @param[in] ParentBlockIo Parent BlockIo interface\r
604 @param[in] ParentDevicePath Parent Device Path\r
605 @param[in] DevicePathNode Child Device Path node\r
606 @param[in] Start Start Block\r
607 @param[in] End End Block\r
608 @param[in] BlockSize Child block size\r
609 @param[in] InstallEspGuid Flag to install EFI System Partition GUID on handle\r
610\r
611 @retval EFI_SUCCESS A child handle was added\r
612 @retval other A child handle was not added\r
613\r
614**/\r
615EFI_STATUS\r
616PartitionInstallChildHandle (\r
617 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
618 IN EFI_HANDLE ParentHandle,\r
619 IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,\r
620 IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,\r
621 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
622 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,\r
623 IN EFI_LBA Start,\r
624 IN EFI_LBA End,\r
625 IN UINT32 BlockSize,\r
626 IN BOOLEAN InstallEspGuid\r
627 )\r
628{\r
629 EFI_STATUS Status;\r
630 PARTITION_PRIVATE_DATA *Private;\r
631\r
632 Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));\r
633 if (Private == NULL) {\r
634 return EFI_OUT_OF_RESOURCES;\r
635 }\r
636\r
637 Private->Signature = PARTITION_PRIVATE_DATA_SIGNATURE;\r
638\r
639 Private->Start = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);\r
640 Private->End = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);\r
641\r
642 Private->BlockSize = BlockSize;\r
643 Private->ParentBlockIo = ParentBlockIo;\r
644 Private->DiskIo = ParentDiskIo;\r
645\r
9e9f86ec 646 Private->BlockIo.Revision = ParentBlockIo->Revision;\r
adbcbf8f 647\r
648 Private->BlockIo.Media = &Private->Media;\r
f1e2b802 649 CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));\r
adbcbf8f 650 Private->Media.LogicalPartition = TRUE;\r
67f802ed
RN
651\r
652 //\r
653 // Logical BlockIo instance doesn't have IoAlign restriction because it implements block io operation based on DiskIo\r
654 //\r
655 Private->Media.IoAlign = 0;\r
adbcbf8f 656 Private->Media.LastBlock = DivU64x32 (\r
657 MultU64x32 (\r
658 End - Start + 1,\r
659 ParentBlockIo->Media->BlockSize\r
660 ),\r
661 BlockSize\r
662 ) - 1;\r
663\r
67f802ed 664 Private->Media.BlockSize = (UINT32) BlockSize;\r
adbcbf8f 665\r
fe3b68bb
RN
666 //\r
667 // Per UEFI Spec, LowestAlignedLba and LogicalBlocksPerPhysicalBlock must be 0\r
668 // for logical partitions.\r
669 //\r
670 if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION2) {\r
671 Private->BlockIo.Media->LowestAlignedLba = 0;\r
672 Private->BlockIo.Media->LogicalBlocksPerPhysicalBlock = 0;\r
673 }\r
674\r
adbcbf8f 675 Private->BlockIo.Reset = PartitionReset;\r
676 Private->BlockIo.ReadBlocks = PartitionReadBlocks;\r
677 Private->BlockIo.WriteBlocks = PartitionWriteBlocks;\r
678 Private->BlockIo.FlushBlocks = PartitionFlushBlocks;\r
679\r
680 Private->DevicePath = AppendDevicePathNode (ParentDevicePath, DevicePathNode);\r
681\r
682 if (Private->DevicePath == NULL) {\r
683 FreePool (Private);\r
684 return EFI_OUT_OF_RESOURCES;\r
685 }\r
686\r
687 if (InstallEspGuid) {\r
688 Private->EspGuid = &gEfiPartTypeSystemPartGuid;\r
689 } else {\r
690 //\r
691 // If NULL InstallMultipleProtocolInterfaces will ignore it.\r
692 //\r
693 Private->EspGuid = NULL;\r
694 }\r
695 //\r
696 // Create the new handle\r
697 //\r
698 Private->Handle = NULL;\r
699 Status = gBS->InstallMultipleProtocolInterfaces (\r
700 &Private->Handle,\r
701 &gEfiDevicePathProtocolGuid,\r
702 Private->DevicePath,\r
703 &gEfiBlockIoProtocolGuid,\r
704 &Private->BlockIo,\r
705 Private->EspGuid,\r
706 NULL,\r
707 NULL\r
708 );\r
709\r
710 if (!EFI_ERROR (Status)) {\r
711 //\r
712 // Open the Parent Handle for the child\r
713 //\r
714 Status = gBS->OpenProtocol (\r
715 ParentHandle,\r
716 &gEfiDiskIoProtocolGuid,\r
717 (VOID **) &ParentDiskIo,\r
718 This->DriverBindingHandle,\r
719 Private->Handle,\r
720 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
721 );\r
722 } else {\r
723 FreePool (Private->DevicePath);\r
724 FreePool (Private);\r
725 }\r
726\r
727 return Status;\r
728}\r
729\r
730\r
731/**\r
732 The user Entry Point for module Partition. The user code starts with this function.\r
733\r
734 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
735 @param[in] SystemTable A pointer to the EFI System Table.\r
736 \r
737 @retval EFI_SUCCESS The entry point is executed successfully.\r
738 @retval other Some error occurs when executing this entry point.\r
739\r
740**/\r
741EFI_STATUS\r
742EFIAPI\r
743InitializePartition (\r
744 IN EFI_HANDLE ImageHandle,\r
745 IN EFI_SYSTEM_TABLE *SystemTable\r
746 )\r
747{\r
748 EFI_STATUS Status;\r
749\r
750 //\r
751 // Install driver model protocol(s).\r
752 //\r
d38a0f44 753 Status = EfiLibInstallDriverBindingComponentName2 (\r
adbcbf8f 754 ImageHandle,\r
755 SystemTable,\r
756 &gPartitionDriverBinding,\r
757 ImageHandle,\r
758 &gPartitionComponentName,\r
d38a0f44 759 &gPartitionComponentName2\r
adbcbf8f 760 );\r
761 ASSERT_EFI_ERROR (Status);\r
762\r
763\r
764 return Status;\r
765}\r
766\r