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