]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c
MdeModulePkg DiskIoDxe: Check for MediaPresent in DiskIo2ReadWriteDisk()
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / DiskIoDxe / DiskIo.c
1 /** @file
2 DiskIo driver that lays on every BlockIo protocol in the system.
3 DiskIo converts a block oriented device to a byte oriented device.
4
5 Disk access may have to handle unaligned request about sector boundaries.
6 There are three cases:
7 UnderRun - The first byte is not on a sector boundary or the read request is
8 less than a sector in length.
9 Aligned - A read of N contiguous sectors.
10 OverRun - The last byte is not on a sector boundary.
11
12 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
13 This program and the accompanying materials
14 are licensed and made available under the terms and conditions of the BSD License
15 which accompanies this distribution. The full text of the license may be found at
16 http://opensource.org/licenses/bsd-license.php
17
18 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20
21 **/
22
23 #include "DiskIo.h"
24
25 //
26 // Driver binding protocol implementation for DiskIo driver.
27 //
28 EFI_DRIVER_BINDING_PROTOCOL gDiskIoDriverBinding = {
29 DiskIoDriverBindingSupported,
30 DiskIoDriverBindingStart,
31 DiskIoDriverBindingStop,
32 0xa,
33 NULL,
34 NULL
35 };
36
37 //
38 // Template for DiskIo private data structure.
39 // The pointer to BlockIo protocol interface is assigned dynamically.
40 //
41 DISK_IO_PRIVATE_DATA gDiskIoPrivateDataTemplate = {
42 DISK_IO_PRIVATE_DATA_SIGNATURE,
43 {
44 EFI_DISK_IO_PROTOCOL_REVISION,
45 DiskIoReadDisk,
46 DiskIoWriteDisk
47 },
48 {
49 EFI_DISK_IO2_PROTOCOL_REVISION,
50 DiskIo2Cancel,
51 DiskIo2ReadDiskEx,
52 DiskIo2WriteDiskEx,
53 DiskIo2FlushDiskEx
54 }
55 };
56
57 /**
58 Test to see if this driver supports ControllerHandle.
59
60 @param This Protocol instance pointer.
61 @param ControllerHandle Handle of device to test
62 @param RemainingDevicePath Optional parameter use to pick a specific child
63 device to start.
64
65 @retval EFI_SUCCESS This driver supports this device
66 @retval EFI_ALREADY_STARTED This driver is already running on this device
67 @retval other This driver does not support this device
68
69 **/
70 EFI_STATUS
71 EFIAPI
72 DiskIoDriverBindingSupported (
73 IN EFI_DRIVER_BINDING_PROTOCOL *This,
74 IN EFI_HANDLE ControllerHandle,
75 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
76 )
77 {
78 EFI_STATUS Status;
79 EFI_BLOCK_IO_PROTOCOL *BlockIo;
80
81 //
82 // Open the IO Abstraction(s) needed to perform the supported test.
83 //
84 Status = gBS->OpenProtocol (
85 ControllerHandle,
86 &gEfiBlockIoProtocolGuid,
87 (VOID **) &BlockIo,
88 This->DriverBindingHandle,
89 ControllerHandle,
90 EFI_OPEN_PROTOCOL_BY_DRIVER
91 );
92 if (EFI_ERROR (Status)) {
93 return Status;
94 }
95
96 //
97 // Close the I/O Abstraction(s) used to perform the supported test.
98 //
99 gBS->CloseProtocol (
100 ControllerHandle,
101 &gEfiBlockIoProtocolGuid,
102 This->DriverBindingHandle,
103 ControllerHandle
104 );
105 return EFI_SUCCESS;
106 }
107
108
109 /**
110 Start this driver on ControllerHandle by opening a Block IO protocol and
111 installing a Disk IO protocol on ControllerHandle.
112
113 @param This Protocol instance pointer.
114 @param ControllerHandle Handle of device to bind driver to
115 @param RemainingDevicePath Optional parameter use to pick a specific child
116 device to start.
117
118 @retval EFI_SUCCESS This driver is added to ControllerHandle
119 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
120 @retval other This driver does not support this device
121
122 **/
123 EFI_STATUS
124 EFIAPI
125 DiskIoDriverBindingStart (
126 IN EFI_DRIVER_BINDING_PROTOCOL *This,
127 IN EFI_HANDLE ControllerHandle,
128 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
129 )
130 {
131 EFI_STATUS Status;
132 DISK_IO_PRIVATE_DATA *Instance;
133 EFI_TPL OldTpl;
134
135 Instance = NULL;
136
137 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
138
139 //
140 // Connect to the Block IO and Block IO2 interface on ControllerHandle.
141 //
142 Status = gBS->OpenProtocol (
143 ControllerHandle,
144 &gEfiBlockIoProtocolGuid,
145 (VOID **) &gDiskIoPrivateDataTemplate.BlockIo,
146 This->DriverBindingHandle,
147 ControllerHandle,
148 EFI_OPEN_PROTOCOL_BY_DRIVER
149 );
150 if (EFI_ERROR (Status)) {
151 goto ErrorExit1;
152 }
153
154 Status = gBS->OpenProtocol (
155 ControllerHandle,
156 &gEfiBlockIo2ProtocolGuid,
157 (VOID **) &gDiskIoPrivateDataTemplate.BlockIo2,
158 This->DriverBindingHandle,
159 ControllerHandle,
160 EFI_OPEN_PROTOCOL_BY_DRIVER
161 );
162 if (EFI_ERROR (Status)) {
163 gDiskIoPrivateDataTemplate.BlockIo2 = NULL;
164 }
165
166 //
167 // Initialize the Disk IO device instance.
168 //
169 Instance = AllocateCopyPool (sizeof (DISK_IO_PRIVATE_DATA), &gDiskIoPrivateDataTemplate);
170 if (Instance == NULL) {
171 Status = EFI_OUT_OF_RESOURCES;
172 goto ErrorExit;
173 }
174
175 //
176 // The BlockSize and IoAlign of BlockIo and BlockIo2 should equal.
177 //
178 ASSERT ((Instance->BlockIo2 == NULL) ||
179 ((Instance->BlockIo->Media->IoAlign == Instance->BlockIo2->Media->IoAlign) &&
180 (Instance->BlockIo->Media->BlockSize == Instance->BlockIo2->Media->BlockSize)
181 ));
182
183 InitializeListHead (&Instance->TaskQueue);
184 EfiInitializeLock (&Instance->TaskQueueLock, TPL_NOTIFY);
185 Instance->SharedWorkingBuffer = AllocateAlignedPages (
186 EFI_SIZE_TO_PAGES (PcdGet32 (PcdDiskIoDataBufferBlockNum) * Instance->BlockIo->Media->BlockSize),
187 Instance->BlockIo->Media->IoAlign
188 );
189 if (Instance->SharedWorkingBuffer == NULL) {
190 Status = EFI_OUT_OF_RESOURCES;
191 goto ErrorExit;
192 }
193
194 //
195 // Install protocol interfaces for the Disk IO device.
196 //
197 if (Instance->BlockIo2 != NULL) {
198 Status = gBS->InstallMultipleProtocolInterfaces (
199 &ControllerHandle,
200 &gEfiDiskIoProtocolGuid, &Instance->DiskIo,
201 &gEfiDiskIo2ProtocolGuid, &Instance->DiskIo2,
202 NULL
203 );
204 } else {
205 Status = gBS->InstallMultipleProtocolInterfaces (
206 &ControllerHandle,
207 &gEfiDiskIoProtocolGuid, &Instance->DiskIo,
208 NULL
209 );
210 }
211
212 ErrorExit:
213 if (EFI_ERROR (Status)) {
214 if (Instance != NULL && Instance->SharedWorkingBuffer != NULL) {
215 FreeAlignedPages (
216 Instance->SharedWorkingBuffer,
217 EFI_SIZE_TO_PAGES (PcdGet32 (PcdDiskIoDataBufferBlockNum) * Instance->BlockIo->Media->BlockSize)
218 );
219 }
220
221 if (Instance != NULL) {
222 FreePool (Instance);
223 }
224
225 gBS->CloseProtocol (
226 ControllerHandle,
227 &gEfiBlockIoProtocolGuid,
228 This->DriverBindingHandle,
229 ControllerHandle
230 );
231 }
232
233 ErrorExit1:
234 gBS->RestoreTPL (OldTpl);
235 return Status;
236 }
237
238 /**
239 Stop this driver on ControllerHandle by removing Disk IO protocol and closing
240 the Block IO protocol on ControllerHandle.
241
242 @param This Protocol instance pointer.
243 @param ControllerHandle Handle of device to stop driver on
244 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
245 children is zero stop the entire bus driver.
246 @param ChildHandleBuffer List of Child Handles to Stop.
247
248 @retval EFI_SUCCESS This driver is removed ControllerHandle
249 @retval other This driver was not removed from this device
250
251 **/
252 EFI_STATUS
253 EFIAPI
254 DiskIoDriverBindingStop (
255 IN EFI_DRIVER_BINDING_PROTOCOL *This,
256 IN EFI_HANDLE ControllerHandle,
257 IN UINTN NumberOfChildren,
258 IN EFI_HANDLE *ChildHandleBuffer
259 )
260 {
261 EFI_STATUS Status;
262 EFI_DISK_IO_PROTOCOL *DiskIo;
263 EFI_DISK_IO2_PROTOCOL *DiskIo2;
264 DISK_IO_PRIVATE_DATA *Instance;
265 BOOLEAN AllTaskDone;
266
267 //
268 // Get our context back.
269 //
270 Status = gBS->OpenProtocol (
271 ControllerHandle,
272 &gEfiDiskIoProtocolGuid,
273 (VOID **) &DiskIo,
274 This->DriverBindingHandle,
275 ControllerHandle,
276 EFI_OPEN_PROTOCOL_GET_PROTOCOL
277 );
278 if (EFI_ERROR (Status)) {
279 return Status;
280 }
281 Status = gBS->OpenProtocol (
282 ControllerHandle,
283 &gEfiDiskIo2ProtocolGuid,
284 (VOID **) &DiskIo2,
285 This->DriverBindingHandle,
286 ControllerHandle,
287 EFI_OPEN_PROTOCOL_GET_PROTOCOL
288 );
289 if (EFI_ERROR (Status)) {
290 DiskIo2 = NULL;
291 }
292
293 Instance = DISK_IO_PRIVATE_DATA_FROM_DISK_IO (DiskIo);
294
295 if (DiskIo2 != NULL) {
296 //
297 // Call BlockIo2::Reset() to terminate any in-flight non-blocking I/O requests
298 //
299 ASSERT (Instance->BlockIo2 != NULL);
300 Status = Instance->BlockIo2->Reset (Instance->BlockIo2, FALSE);
301 if (EFI_ERROR (Status)) {
302 return Status;
303 }
304 Status = gBS->UninstallMultipleProtocolInterfaces (
305 ControllerHandle,
306 &gEfiDiskIoProtocolGuid, &Instance->DiskIo,
307 &gEfiDiskIo2ProtocolGuid, &Instance->DiskIo2,
308 NULL
309 );
310 } else {
311 Status = gBS->UninstallMultipleProtocolInterfaces (
312 ControllerHandle,
313 &gEfiDiskIoProtocolGuid, &Instance->DiskIo,
314 NULL
315 );
316 }
317 if (!EFI_ERROR (Status)) {
318
319 do {
320 EfiAcquireLock (&Instance->TaskQueueLock);
321 AllTaskDone = IsListEmpty (&Instance->TaskQueue);
322 EfiReleaseLock (&Instance->TaskQueueLock);
323 } while (!AllTaskDone);
324
325 FreeAlignedPages (
326 Instance->SharedWorkingBuffer,
327 EFI_SIZE_TO_PAGES (PcdGet32 (PcdDiskIoDataBufferBlockNum) * Instance->BlockIo->Media->BlockSize)
328 );
329
330 Status = gBS->CloseProtocol (
331 ControllerHandle,
332 &gEfiBlockIoProtocolGuid,
333 This->DriverBindingHandle,
334 ControllerHandle
335 );
336 ASSERT_EFI_ERROR (Status);
337 if (DiskIo2 != NULL) {
338 Status = gBS->CloseProtocol (
339 ControllerHandle,
340 &gEfiBlockIo2ProtocolGuid,
341 This->DriverBindingHandle,
342 ControllerHandle
343 );
344 ASSERT_EFI_ERROR (Status);
345 }
346
347 FreePool (Instance);
348 }
349
350 return Status;
351 }
352
353
354 /**
355 Destroy the sub task.
356
357 @param Instance Pointer to the DISK_IO_PRIVATE_DATA.
358 @param Subtask Subtask.
359
360 @return LIST_ENTRY * Pointer to the next link of subtask.
361 **/
362 LIST_ENTRY *
363 DiskIoDestroySubtask (
364 IN DISK_IO_PRIVATE_DATA *Instance,
365 IN DISK_IO_SUBTASK *Subtask
366 )
367 {
368 LIST_ENTRY *Link;
369
370 if (Subtask->Task != NULL) {
371 EfiAcquireLock (&Subtask->Task->SubtasksLock);
372 }
373 Link = RemoveEntryList (&Subtask->Link);
374 if (Subtask->Task != NULL) {
375 EfiReleaseLock (&Subtask->Task->SubtasksLock);
376 }
377
378 if (!Subtask->Blocking) {
379 if (Subtask->WorkingBuffer != NULL) {
380 FreeAlignedPages (
381 Subtask->WorkingBuffer,
382 Subtask->Length < Instance->BlockIo->Media->BlockSize
383 ? EFI_SIZE_TO_PAGES (Instance->BlockIo->Media->BlockSize)
384 : EFI_SIZE_TO_PAGES (Subtask->Length)
385 );
386 }
387 if (Subtask->BlockIo2Token.Event != NULL) {
388 gBS->CloseEvent (Subtask->BlockIo2Token.Event);
389 }
390 }
391 FreePool (Subtask);
392
393 return Link;
394 }
395
396 /**
397 The callback for the BlockIo2 ReadBlocksEx/WriteBlocksEx.
398 @param Event Event whose notification function is being invoked.
399 @param Context The pointer to the notification function's context,
400 which points to the DISK_IO_SUBTASK instance.
401 **/
402 VOID
403 EFIAPI
404 DiskIo2OnReadWriteComplete (
405 IN EFI_EVENT Event,
406 IN VOID *Context
407 )
408 {
409 DISK_IO_SUBTASK *Subtask;
410 DISK_IO2_TASK *Task;
411 EFI_STATUS TransactionStatus;
412 DISK_IO_PRIVATE_DATA *Instance;
413
414 Subtask = (DISK_IO_SUBTASK *) Context;
415 TransactionStatus = Subtask->BlockIo2Token.TransactionStatus;
416 Task = Subtask->Task;
417 Instance = Task->Instance;
418
419 ASSERT (Subtask->Signature == DISK_IO_SUBTASK_SIGNATURE);
420 ASSERT (Instance->Signature == DISK_IO_PRIVATE_DATA_SIGNATURE);
421 ASSERT (Task->Signature == DISK_IO2_TASK_SIGNATURE);
422
423 if ((Subtask->WorkingBuffer != NULL) && !EFI_ERROR (TransactionStatus) &&
424 (Task->Token != NULL) && !Subtask->Write
425 ) {
426 CopyMem (Subtask->Buffer, Subtask->WorkingBuffer + Subtask->Offset, Subtask->Length);
427 }
428
429 DiskIoDestroySubtask (Instance, Subtask);
430
431 if (EFI_ERROR (TransactionStatus) || IsListEmpty (&Task->Subtasks)) {
432 if (Task->Token != NULL) {
433 //
434 // Signal error status once the subtask is failed.
435 // Or signal the last status once the last subtask is finished.
436 //
437 Task->Token->TransactionStatus = TransactionStatus;
438 gBS->SignalEvent (Task->Token->Event);
439
440 //
441 // Mark token to NULL indicating the Task is a dead task.
442 //
443 Task->Token = NULL;
444 }
445 }
446 }
447
448 /**
449 Create the subtask.
450
451 @param Write TRUE: Write request; FALSE: Read request.
452 @param Lba The starting logical block address to read from on the device.
453 @param Offset The starting byte offset to read from the LBA.
454 @param Length The number of bytes to read from the device.
455 @param WorkingBuffer The aligned buffer to hold the data for reading or writing.
456 @param Buffer The buffer to hold the data for reading or writing.
457 @param Blocking TRUE: Blocking request; FALSE: Non-blocking request.
458
459 @return A pointer to the created subtask.
460 **/
461 DISK_IO_SUBTASK *
462 DiskIoCreateSubtask (
463 IN BOOLEAN Write,
464 IN UINT64 Lba,
465 IN UINT32 Offset,
466 IN UINTN Length,
467 IN VOID *WorkingBuffer, OPTIONAL
468 IN VOID *Buffer,
469 IN BOOLEAN Blocking
470 )
471 {
472 DISK_IO_SUBTASK *Subtask;
473 EFI_STATUS Status;
474
475 Subtask = AllocateZeroPool (sizeof (DISK_IO_SUBTASK));
476 if (Subtask == NULL) {
477 return NULL;
478 }
479 Subtask->Signature = DISK_IO_SUBTASK_SIGNATURE;
480 Subtask->Write = Write;
481 Subtask->Lba = Lba;
482 Subtask->Offset = Offset;
483 Subtask->Length = Length;
484 Subtask->WorkingBuffer = WorkingBuffer;
485 Subtask->Buffer = Buffer;
486 Subtask->Blocking = Blocking;
487 if (!Blocking) {
488 Status = gBS->CreateEvent (
489 EVT_NOTIFY_SIGNAL,
490 TPL_NOTIFY,
491 DiskIo2OnReadWriteComplete,
492 Subtask,
493 &Subtask->BlockIo2Token.Event
494 );
495 if (EFI_ERROR (Status)) {
496 FreePool (Subtask);
497 return NULL;
498 }
499 }
500 DEBUG ((
501 EFI_D_BLKIO,
502 " %c:Lba/Offset/Length/WorkingBuffer/Buffer = %016lx/%08x/%08x/%08x/%08x\n",
503 Write ? 'W': 'R', Lba, Offset, Length, WorkingBuffer, Buffer
504 ));
505
506 return Subtask;
507 }
508
509 /**
510 Create the subtask list.
511
512 @param Instance Pointer to the DISK_IO_PRIVATE_DATA.
513 @param Write TRUE: Write request; FALSE: Read request.
514 @param Offset The starting byte offset to read from the device.
515 @param BufferSize The size in bytes of Buffer. The number of bytes to read from the device.
516 @param Buffer A pointer to the buffer for the data.
517 @param Blocking TRUE: Blocking request; FALSE: Non-blocking request.
518 @param SharedWorkingBuffer The aligned buffer to hold the data for reading or writing.
519 @param Subtasks The subtask list header.
520
521 @retval TRUE The subtask list is created successfully.
522 @retval FALSE The subtask list is not created.
523 **/
524 BOOLEAN
525 DiskIoCreateSubtaskList (
526 IN DISK_IO_PRIVATE_DATA *Instance,
527 IN BOOLEAN Write,
528 IN UINT64 Offset,
529 IN UINTN BufferSize,
530 IN VOID *Buffer,
531 IN BOOLEAN Blocking,
532 IN VOID *SharedWorkingBuffer,
533 IN OUT LIST_ENTRY *Subtasks
534 )
535 {
536 UINT32 BlockSize;
537 UINT32 IoAlign;
538 UINT64 Lba;
539 UINT64 OverRunLba;
540 UINT32 UnderRun;
541 UINT32 OverRun;
542 UINT8 *BufferPtr;
543 UINTN Length;
544 UINTN DataBufferSize;
545 DISK_IO_SUBTASK *Subtask;
546 VOID *WorkingBuffer;
547 LIST_ENTRY *Link;
548
549 DEBUG ((EFI_D_BLKIO, "DiskIo: Create subtasks for task: Offset/BufferSize/Buffer = %016lx/%08x/%08x\n", Offset, BufferSize, Buffer));
550
551 BlockSize = Instance->BlockIo->Media->BlockSize;
552 IoAlign = Instance->BlockIo->Media->IoAlign;
553 if (IoAlign == 0) {
554 IoAlign = 1;
555 }
556
557 Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun);
558 BufferPtr = (UINT8 *) Buffer;
559
560 //
561 // Special handling for zero BufferSize
562 //
563 if (BufferSize == 0) {
564 Subtask = DiskIoCreateSubtask (Write, Lba, UnderRun, 0, NULL, BufferPtr, Blocking);
565 if (Subtask == NULL) {
566 goto Done;
567 }
568 InsertTailList (Subtasks, &Subtask->Link);
569 return TRUE;
570 }
571
572 if (UnderRun != 0) {
573 Length = MIN (BlockSize - UnderRun, BufferSize);
574 if (Blocking) {
575 WorkingBuffer = SharedWorkingBuffer;
576 } else {
577 WorkingBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BlockSize), IoAlign);
578 if (WorkingBuffer == NULL) {
579 goto Done;
580 }
581 }
582 if (Write) {
583 //
584 // A half write operation can be splitted to a blocking block-read and half write operation
585 // This can simplify the sub task processing logic
586 //
587 Subtask = DiskIoCreateSubtask (FALSE, Lba, 0, BlockSize, NULL, WorkingBuffer, TRUE);
588 if (Subtask == NULL) {
589 goto Done;
590 }
591 InsertTailList (Subtasks, &Subtask->Link);
592 }
593
594 Subtask = DiskIoCreateSubtask (Write, Lba, UnderRun, Length, WorkingBuffer, BufferPtr, Blocking);
595 if (Subtask == NULL) {
596 goto Done;
597 }
598 InsertTailList (Subtasks, &Subtask->Link);
599
600 BufferPtr += Length;
601 Offset += Length;
602 BufferSize -= Length;
603 Lba ++;
604 }
605
606 OverRunLba = Lba + DivU64x32Remainder (BufferSize, BlockSize, &OverRun);
607 BufferSize -= OverRun;
608
609 if (OverRun != 0) {
610 if (Blocking) {
611 WorkingBuffer = SharedWorkingBuffer;
612 } else {
613 WorkingBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BlockSize), IoAlign);
614 if (WorkingBuffer == NULL) {
615 goto Done;
616 }
617 }
618 if (Write) {
619 //
620 // A half write operation can be splitted to a blocking block-read and half write operation
621 // This can simplify the sub task processing logic
622 //
623 Subtask = DiskIoCreateSubtask (FALSE, OverRunLba, 0, BlockSize, NULL, WorkingBuffer, TRUE);
624 if (Subtask == NULL) {
625 goto Done;
626 }
627 InsertTailList (Subtasks, &Subtask->Link);
628 }
629
630 Subtask = DiskIoCreateSubtask (Write, OverRunLba, 0, OverRun, WorkingBuffer, BufferPtr + BufferSize, Blocking);
631 if (Subtask == NULL) {
632 goto Done;
633 }
634 InsertTailList (Subtasks, &Subtask->Link);
635 }
636
637 if (OverRunLba > Lba) {
638 //
639 // If the DiskIo maps directly to a BlockIo device do the read.
640 //
641 if (ALIGN_POINTER (BufferPtr, IoAlign) == BufferPtr) {
642 Subtask = DiskIoCreateSubtask (Write, Lba, 0, BufferSize, NULL, BufferPtr, Blocking);
643 if (Subtask == NULL) {
644 goto Done;
645 }
646 InsertTailList (Subtasks, &Subtask->Link);
647
648 BufferPtr += BufferSize;
649 Offset += BufferSize;
650 BufferSize -= BufferSize;
651
652 } else {
653 if (Blocking) {
654 //
655 // Use the allocated buffer instead of the original buffer
656 // to avoid alignment issue.
657 //
658 for (; Lba < OverRunLba; Lba += PcdGet32 (PcdDiskIoDataBufferBlockNum)) {
659 DataBufferSize = MIN (BufferSize, PcdGet32 (PcdDiskIoDataBufferBlockNum) * BlockSize);
660
661 Subtask = DiskIoCreateSubtask (Write, Lba, 0, DataBufferSize, SharedWorkingBuffer, BufferPtr, Blocking);
662 if (Subtask == NULL) {
663 goto Done;
664 }
665 InsertTailList (Subtasks, &Subtask->Link);
666
667 BufferPtr += DataBufferSize;
668 Offset += DataBufferSize;
669 BufferSize -= DataBufferSize;
670 }
671 } else {
672 WorkingBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), IoAlign);
673 if (WorkingBuffer == NULL) {
674 //
675 // If there is not enough memory, downgrade to blocking access
676 //
677 DEBUG ((EFI_D_VERBOSE, "DiskIo: No enough memory so downgrade to blocking access\n"));
678 if (!DiskIoCreateSubtaskList (Instance, Write, Offset, BufferSize, BufferPtr, TRUE, SharedWorkingBuffer, Subtasks)) {
679 goto Done;
680 }
681 } else {
682 Subtask = DiskIoCreateSubtask (Write, Lba, 0, BufferSize, WorkingBuffer, BufferPtr, Blocking);
683 if (Subtask == NULL) {
684 goto Done;
685 }
686 InsertTailList (Subtasks, &Subtask->Link);
687 }
688
689 BufferPtr += BufferSize;
690 Offset += BufferSize;
691 BufferSize -= BufferSize;
692 }
693 }
694 }
695
696 ASSERT (BufferSize == 0);
697
698 return TRUE;
699
700 Done:
701 //
702 // Remove all the subtasks.
703 //
704 for (Link = GetFirstNode (Subtasks); !IsNull (Subtasks, Link); ) {
705 Subtask = CR (Link, DISK_IO_SUBTASK, Link, DISK_IO_SUBTASK_SIGNATURE);
706 Link = DiskIoDestroySubtask (Instance, Subtask);
707 }
708 return FALSE;
709 }
710
711 /**
712 Terminate outstanding asynchronous requests to a device.
713
714 @param This Indicates a pointer to the calling context.
715
716 @retval EFI_SUCCESS All outstanding requests were successfully terminated.
717 @retval EFI_DEVICE_ERROR The device reported an error while performing the cancel
718 operation.
719 **/
720 EFI_STATUS
721 EFIAPI
722 DiskIo2Cancel (
723 IN EFI_DISK_IO2_PROTOCOL *This
724 )
725 {
726 DISK_IO_PRIVATE_DATA *Instance;
727 DISK_IO2_TASK *Task;
728 LIST_ENTRY *Link;
729
730 Instance = DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This);
731
732 EfiAcquireLock (&Instance->TaskQueueLock);
733
734 for (Link = GetFirstNode (&Instance->TaskQueue)
735 ; !IsNull (&Instance->TaskQueue, Link)
736 ; Link = GetNextNode (&Instance->TaskQueue, Link)
737 ) {
738 Task = CR (Link, DISK_IO2_TASK, Link, DISK_IO2_TASK_SIGNATURE);
739
740 if (Task->Token != NULL) {
741 Task->Token->TransactionStatus = EFI_ABORTED;
742 gBS->SignalEvent (Task->Token->Event);
743 //
744 // Set Token to NULL so that the further BlockIo2 responses will be ignored
745 //
746 Task->Token = NULL;
747 }
748 }
749
750 EfiReleaseLock (&Instance->TaskQueueLock);
751
752 return EFI_SUCCESS;
753 }
754
755 /**
756 Remove the completed tasks from Instance->TaskQueue. Completed tasks are those who don't have any subtasks.
757
758 @param Instance Pointer to the DISK_IO_PRIVATE_DATA.
759
760 @retval TRUE The Instance->TaskQueue is empty after the completed tasks are removed.
761 @retval FALSE The Instance->TaskQueue is not empty after the completed tasks are removed.
762 **/
763 BOOLEAN
764 DiskIo2RemoveCompletedTask (
765 IN DISK_IO_PRIVATE_DATA *Instance
766 )
767 {
768 BOOLEAN QueueEmpty;
769 LIST_ENTRY *Link;
770 DISK_IO2_TASK *Task;
771
772 QueueEmpty = TRUE;
773
774 EfiAcquireLock (&Instance->TaskQueueLock);
775 for (Link = GetFirstNode (&Instance->TaskQueue); !IsNull (&Instance->TaskQueue, Link); ) {
776 Task = CR (Link, DISK_IO2_TASK, Link, DISK_IO2_TASK_SIGNATURE);
777 if (IsListEmpty (&Task->Subtasks)) {
778 Link = RemoveEntryList (&Task->Link);
779 ASSERT (Task->Token == NULL);
780 FreePool (Task);
781 } else {
782 Link = GetNextNode (&Instance->TaskQueue, Link);
783 QueueEmpty = FALSE;
784 }
785 }
786 EfiReleaseLock (&Instance->TaskQueueLock);
787
788 return QueueEmpty;
789 }
790
791 /**
792 Common routine to access the disk.
793
794 @param Instance Pointer to the DISK_IO_PRIVATE_DATA.
795 @param Write TRUE: Write operation; FALSE: Read operation.
796 @param MediaId ID of the medium to access.
797 @param Offset The starting byte offset on the logical block I/O device to access.
798 @param Token A pointer to the token associated with the transaction.
799 If this field is NULL, synchronous/blocking IO is performed.
800 @param BufferSize The size in bytes of Buffer. The number of bytes to read from the device.
801 @param Buffer A pointer to the destination buffer for the data.
802 The caller is responsible either having implicit or explicit ownership of the buffer.
803 **/
804 EFI_STATUS
805 DiskIo2ReadWriteDisk (
806 IN DISK_IO_PRIVATE_DATA *Instance,
807 IN BOOLEAN Write,
808 IN UINT32 MediaId,
809 IN UINT64 Offset,
810 IN EFI_DISK_IO2_TOKEN *Token,
811 IN UINTN BufferSize,
812 IN UINT8 *Buffer
813 )
814 {
815 EFI_STATUS Status;
816 EFI_BLOCK_IO_PROTOCOL *BlockIo;
817 EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
818 EFI_BLOCK_IO_MEDIA *Media;
819 LIST_ENTRY *Link;
820 LIST_ENTRY *NextLink;
821 LIST_ENTRY Subtasks;
822 DISK_IO_SUBTASK *Subtask;
823 DISK_IO2_TASK *Task;
824 EFI_TPL OldTpl;
825 BOOLEAN Blocking;
826 BOOLEAN SubtaskBlocking;
827 LIST_ENTRY *SubtasksPtr;
828
829 Task = NULL;
830 BlockIo = Instance->BlockIo;
831 BlockIo2 = Instance->BlockIo2;
832 Media = BlockIo->Media;
833 Status = EFI_SUCCESS;
834 Blocking = (BOOLEAN) ((Token == NULL) || (Token->Event == NULL));
835
836 if (!(Media->MediaPresent)) {
837 return EFI_NO_MEDIA;
838 }
839
840 if (Media->MediaId != MediaId) {
841 return EFI_MEDIA_CHANGED;
842 }
843
844 if (Write && Media->ReadOnly) {
845 return EFI_WRITE_PROTECTED;
846 }
847
848 if (Blocking) {
849 //
850 // Wait till pending async task is completed.
851 //
852 while (!DiskIo2RemoveCompletedTask (Instance));
853
854 SubtasksPtr = &Subtasks;
855 } else {
856 DiskIo2RemoveCompletedTask (Instance);
857 Task = AllocatePool (sizeof (DISK_IO2_TASK));
858 if (Task == NULL) {
859 return EFI_OUT_OF_RESOURCES;
860 }
861
862 EfiAcquireLock (&Instance->TaskQueueLock);
863 InsertTailList (&Instance->TaskQueue, &Task->Link);
864 EfiReleaseLock (&Instance->TaskQueueLock);
865
866 Task->Signature = DISK_IO2_TASK_SIGNATURE;
867 Task->Instance = Instance;
868 Task->Token = Token;
869 EfiInitializeLock (&Task->SubtasksLock, TPL_NOTIFY);
870
871 SubtasksPtr = &Task->Subtasks;
872 }
873
874 InitializeListHead (SubtasksPtr);
875 if (!DiskIoCreateSubtaskList (Instance, Write, Offset, BufferSize, Buffer, Blocking, Instance->SharedWorkingBuffer, SubtasksPtr)) {
876 if (Task != NULL) {
877 FreePool (Task);
878 }
879 return EFI_OUT_OF_RESOURCES;
880 }
881 ASSERT (!IsListEmpty (SubtasksPtr));
882
883 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
884 for ( Link = GetFirstNode (SubtasksPtr), NextLink = GetNextNode (SubtasksPtr, Link)
885 ; !IsNull (SubtasksPtr, Link)
886 ; Link = NextLink, NextLink = GetNextNode (SubtasksPtr, NextLink)
887 ) {
888 Subtask = CR (Link, DISK_IO_SUBTASK, Link, DISK_IO_SUBTASK_SIGNATURE);
889 Subtask->Task = Task;
890 SubtaskBlocking = Subtask->Blocking;
891
892 ASSERT ((Subtask->Length % Media->BlockSize == 0) || (Subtask->Length < Media->BlockSize));
893
894 if (Subtask->Write) {
895 //
896 // Write
897 //
898 if (Subtask->WorkingBuffer != NULL) {
899 //
900 // A sub task before this one should be a block read operation, causing the WorkingBuffer filled with the entire one block data.
901 //
902 CopyMem (Subtask->WorkingBuffer + Subtask->Offset, Subtask->Buffer, Subtask->Length);
903 }
904
905 if (SubtaskBlocking) {
906 Status = BlockIo->WriteBlocks (
907 BlockIo,
908 MediaId,
909 Subtask->Lba,
910 (Subtask->Length % Media->BlockSize == 0) ? Subtask->Length : Media->BlockSize,
911 (Subtask->WorkingBuffer != NULL) ? Subtask->WorkingBuffer : Subtask->Buffer
912 );
913 } else {
914 Status = BlockIo2->WriteBlocksEx (
915 BlockIo2,
916 MediaId,
917 Subtask->Lba,
918 &Subtask->BlockIo2Token,
919 (Subtask->Length % Media->BlockSize == 0) ? Subtask->Length : Media->BlockSize,
920 (Subtask->WorkingBuffer != NULL) ? Subtask->WorkingBuffer : Subtask->Buffer
921 );
922 }
923
924 } else {
925 //
926 // Read
927 //
928 if (SubtaskBlocking) {
929 Status = BlockIo->ReadBlocks (
930 BlockIo,
931 MediaId,
932 Subtask->Lba,
933 (Subtask->Length % Media->BlockSize == 0) ? Subtask->Length : Media->BlockSize,
934 (Subtask->WorkingBuffer != NULL) ? Subtask->WorkingBuffer : Subtask->Buffer
935 );
936 if (!EFI_ERROR (Status) && (Subtask->WorkingBuffer != NULL)) {
937 CopyMem (Subtask->Buffer, Subtask->WorkingBuffer + Subtask->Offset, Subtask->Length);
938 }
939 } else {
940 Status = BlockIo2->ReadBlocksEx (
941 BlockIo2,
942 MediaId,
943 Subtask->Lba,
944 &Subtask->BlockIo2Token,
945 (Subtask->Length % Media->BlockSize == 0) ? Subtask->Length : Media->BlockSize,
946 (Subtask->WorkingBuffer != NULL) ? Subtask->WorkingBuffer : Subtask->Buffer
947 );
948 }
949 }
950
951 if (SubtaskBlocking || EFI_ERROR (Status)) {
952 //
953 // Make sure the subtask list only contains non-blocking subtasks.
954 // Remove failed non-blocking subtasks as well because the callback won't be called.
955 //
956 DiskIoDestroySubtask (Instance, Subtask);
957 }
958
959 if (EFI_ERROR (Status)) {
960 break;
961 }
962 }
963
964 gBS->RaiseTPL (TPL_NOTIFY);
965
966 //
967 // Remove all the remaining subtasks when failure.
968 // We shouldn't remove all the tasks because the non-blocking requests have been submitted and cannot be canceled.
969 //
970 if (EFI_ERROR (Status)) {
971 while (!IsNull (SubtasksPtr, NextLink)) {
972 Subtask = CR (NextLink, DISK_IO_SUBTASK, Link, DISK_IO_SUBTASK_SIGNATURE);
973 NextLink = DiskIoDestroySubtask (Instance, Subtask);
974 }
975 }
976
977 //
978 // It's possible that the non-blocking subtasks finish before raising TPL to NOTIFY,
979 // so the subtasks list might be empty at this point.
980 //
981 if (!Blocking && IsListEmpty (SubtasksPtr)) {
982 EfiAcquireLock (&Instance->TaskQueueLock);
983 RemoveEntryList (&Task->Link);
984 EfiReleaseLock (&Instance->TaskQueueLock);
985
986 if (!EFI_ERROR (Status) && (Task->Token != NULL)) {
987 //
988 // Task->Token should be set to NULL by the DiskIo2OnReadWriteComplete
989 // It it's not, that means the non-blocking request was downgraded to blocking request.
990 //
991 DEBUG ((EFI_D_VERBOSE, "DiskIo: Non-blocking request was downgraded to blocking request, signal event directly.\n"));
992 Task->Token->TransactionStatus = Status;
993 gBS->SignalEvent (Task->Token->Event);
994 }
995
996 FreePool (Task);
997 }
998
999 gBS->RestoreTPL (OldTpl);
1000
1001 return Status;
1002 }
1003
1004 /**
1005 Reads a specified number of bytes from a device.
1006
1007 @param This Indicates a pointer to the calling context.
1008 @param MediaId ID of the medium to be read.
1009 @param Offset The starting byte offset on the logical block I/O device to read from.
1010 @param Token A pointer to the token associated with the transaction.
1011 If this field is NULL, synchronous/blocking IO is performed.
1012 @param BufferSize The size in bytes of Buffer. The number of bytes to read from the device.
1013 @param Buffer A pointer to the destination buffer for the data.
1014 The caller is responsible either having implicit or explicit ownership of the buffer.
1015
1016 @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read correctly from the device.
1017 If Event is not NULL (asynchronous I/O): The request was successfully queued for processing.
1018 Event will be signaled upon completion.
1019 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
1020 @retval EFI_NO_MEDIA There is no medium in the device.
1021 @retval EFI_MEDIA_CHNAGED The MediaId is not for the current medium.
1022 @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not valid for the device.
1023 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1024
1025 **/
1026 EFI_STATUS
1027 EFIAPI
1028 DiskIo2ReadDiskEx (
1029 IN EFI_DISK_IO2_PROTOCOL *This,
1030 IN UINT32 MediaId,
1031 IN UINT64 Offset,
1032 IN OUT EFI_DISK_IO2_TOKEN *Token,
1033 IN UINTN BufferSize,
1034 OUT VOID *Buffer
1035 )
1036 {
1037 return DiskIo2ReadWriteDisk (
1038 DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This),
1039 FALSE, MediaId, Offset, Token, BufferSize, (UINT8 *) Buffer
1040 );
1041 }
1042
1043 /**
1044 Writes a specified number of bytes to a device.
1045
1046 @param This Indicates a pointer to the calling context.
1047 @param MediaId ID of the medium to be written.
1048 @param Offset The starting byte offset on the logical block I/O device to write to.
1049 @param Token A pointer to the token associated with the transaction.
1050 If this field is NULL, synchronous/blocking IO is performed.
1051 @param BufferSize The size in bytes of Buffer. The number of bytes to write to the device.
1052 @param Buffer A pointer to the buffer containing the data to be written.
1053
1054 @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was written correctly to the device.
1055 If Event is not NULL (asynchronous I/O): The request was successfully queued for processing.
1056 Event will be signaled upon completion.
1057 @retval EFI_WRITE_PROTECTED The device cannot be written to.
1058 @retval EFI_DEVICE_ERROR The device reported an error while performing the write operation.
1059 @retval EFI_NO_MEDIA There is no medium in the device.
1060 @retval EFI_MEDIA_CHNAGED The MediaId is not for the current medium.
1061 @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not valid for the device.
1062 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1063
1064 **/
1065 EFI_STATUS
1066 EFIAPI
1067 DiskIo2WriteDiskEx (
1068 IN EFI_DISK_IO2_PROTOCOL *This,
1069 IN UINT32 MediaId,
1070 IN UINT64 Offset,
1071 IN OUT EFI_DISK_IO2_TOKEN *Token,
1072 IN UINTN BufferSize,
1073 IN VOID *Buffer
1074 )
1075 {
1076 return DiskIo2ReadWriteDisk (
1077 DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This),
1078 TRUE, MediaId, Offset, Token, BufferSize, (UINT8 *) Buffer
1079 );
1080 }
1081
1082 /**
1083 The callback for the BlockIo2 FlushBlocksEx.
1084 @param Event Event whose notification function is being invoked.
1085 @param Context The pointer to the notification function's context,
1086 which points to the DISK_IO2_FLUSH_TASK instance.
1087 **/
1088 VOID
1089 EFIAPI
1090 DiskIo2OnFlushComplete (
1091 IN EFI_EVENT Event,
1092 IN VOID *Context
1093 )
1094 {
1095 DISK_IO2_FLUSH_TASK *Task;
1096
1097 gBS->CloseEvent (Event);
1098
1099 Task = (DISK_IO2_FLUSH_TASK *) Context;
1100 ASSERT (Task->Signature == DISK_IO2_FLUSH_TASK_SIGNATURE);
1101 Task->Token->TransactionStatus = Task->BlockIo2Token.TransactionStatus;
1102 gBS->SignalEvent (Task->Token->Event);
1103
1104 FreePool (Task);
1105 }
1106
1107 /**
1108 Flushes all modified data to the physical device.
1109
1110 @param This Indicates a pointer to the calling context.
1111 @param Token A pointer to the token associated with the transaction.
1112 If this field is NULL, synchronous/blocking IO is performed.
1113
1114 @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was flushed successfully to the device.
1115 If Event is not NULL (asynchronous I/O): The request was successfully queued for processing.
1116 Event will be signaled upon completion.
1117 @retval EFI_WRITE_PROTECTED The device cannot be written to.
1118 @retval EFI_DEVICE_ERROR The device reported an error while performing the write operation.
1119 @retval EFI_NO_MEDIA There is no medium in the device.
1120 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1121 **/
1122 EFI_STATUS
1123 EFIAPI
1124 DiskIo2FlushDiskEx (
1125 IN EFI_DISK_IO2_PROTOCOL *This,
1126 IN OUT EFI_DISK_IO2_TOKEN *Token
1127 )
1128 {
1129 EFI_STATUS Status;
1130 DISK_IO2_FLUSH_TASK *Task;
1131 DISK_IO_PRIVATE_DATA *Private;
1132
1133 Private = DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This);
1134
1135 if ((Token != NULL) && (Token->Event != NULL)) {
1136 Task = AllocatePool (sizeof (DISK_IO2_FLUSH_TASK));
1137 if (Task == NULL) {
1138 return EFI_OUT_OF_RESOURCES;
1139 }
1140
1141 Status = gBS->CreateEvent (
1142 EVT_NOTIFY_SIGNAL,
1143 TPL_CALLBACK,
1144 DiskIo2OnFlushComplete,
1145 Task,
1146 &Task->BlockIo2Token.Event
1147 );
1148 if (EFI_ERROR (Status)) {
1149 FreePool (Task);
1150 return Status;
1151 }
1152 Task->Signature = DISK_IO2_FLUSH_TASK_SIGNATURE;
1153 Task->Token = Token;
1154 Status = Private->BlockIo2->FlushBlocksEx (Private->BlockIo2, &Task->BlockIo2Token);
1155 if (EFI_ERROR (Status)) {
1156 gBS->CloseEvent (Task->BlockIo2Token.Event);
1157 FreePool (Task);
1158 }
1159 } else {
1160 Status = Private->BlockIo2->FlushBlocksEx (Private->BlockIo2, NULL);
1161 }
1162
1163 return Status;
1164 }
1165
1166 /**
1167 Read BufferSize bytes from Offset into Buffer.
1168 Reads may support reads that are not aligned on
1169 sector boundaries. There are three cases:
1170 UnderRun - The first byte is not on a sector boundary or the read request is
1171 less than a sector in length.
1172 Aligned - A read of N contiguous sectors.
1173 OverRun - The last byte is not on a sector boundary.
1174
1175 @param This Protocol instance pointer.
1176 @param MediaId Id of the media, changes every time the media is replaced.
1177 @param Offset The starting byte offset to read from
1178 @param BufferSize Size of Buffer
1179 @param Buffer Buffer containing read data
1180
1181 @retval EFI_SUCCESS The data was read correctly from the device.
1182 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
1183 @retval EFI_NO_MEDIA There is no media in the device.
1184 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
1185 @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
1186 valid for the device.
1187
1188 **/
1189 EFI_STATUS
1190 EFIAPI
1191 DiskIoReadDisk (
1192 IN EFI_DISK_IO_PROTOCOL *This,
1193 IN UINT32 MediaId,
1194 IN UINT64 Offset,
1195 IN UINTN BufferSize,
1196 OUT VOID *Buffer
1197 )
1198 {
1199 return DiskIo2ReadWriteDisk (
1200 DISK_IO_PRIVATE_DATA_FROM_DISK_IO (This),
1201 FALSE, MediaId, Offset, NULL, BufferSize, (UINT8 *) Buffer
1202 );
1203 }
1204
1205
1206 /**
1207 Writes BufferSize bytes from Buffer into Offset.
1208 Writes may require a read modify write to support writes that are not
1209 aligned on sector boundaries. There are three cases:
1210 UnderRun - The first byte is not on a sector boundary or the write request
1211 is less than a sector in length. Read modify write is required.
1212 Aligned - A write of N contiguous sectors.
1213 OverRun - The last byte is not on a sector boundary. Read modified write
1214 required.
1215
1216 @param This Protocol instance pointer.
1217 @param MediaId Id of the media, changes every time the media is replaced.
1218 @param Offset The starting byte offset to read from
1219 @param BufferSize Size of Buffer
1220 @param Buffer Buffer containing read data
1221
1222 @retval EFI_SUCCESS The data was written correctly to the device.
1223 @retval EFI_WRITE_PROTECTED The device can not be written to.
1224 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
1225 @retval EFI_NO_MEDIA There is no media in the device.
1226 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
1227 @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not
1228 valid for the device.
1229
1230 **/
1231 EFI_STATUS
1232 EFIAPI
1233 DiskIoWriteDisk (
1234 IN EFI_DISK_IO_PROTOCOL *This,
1235 IN UINT32 MediaId,
1236 IN UINT64 Offset,
1237 IN UINTN BufferSize,
1238 IN VOID *Buffer
1239 )
1240 {
1241 return DiskIo2ReadWriteDisk (
1242 DISK_IO_PRIVATE_DATA_FROM_DISK_IO (This),
1243 TRUE, MediaId, Offset, NULL, BufferSize, (UINT8 *) Buffer
1244 );
1245 }
1246
1247 /**
1248 The user Entry Point for module DiskIo. The user code starts with this function.
1249
1250 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1251 @param[in] SystemTable A pointer to the EFI System Table.
1252
1253 @retval EFI_SUCCESS The entry point is executed successfully.
1254 @retval other Some error occurs when executing this entry point.
1255
1256 **/
1257 EFI_STATUS
1258 EFIAPI
1259 InitializeDiskIo (
1260 IN EFI_HANDLE ImageHandle,
1261 IN EFI_SYSTEM_TABLE *SystemTable
1262 )
1263 {
1264 EFI_STATUS Status;
1265
1266 //
1267 // Install driver model protocol(s).
1268 //
1269 Status = EfiLibInstallDriverBindingComponentName2 (
1270 ImageHandle,
1271 SystemTable,
1272 &gDiskIoDriverBinding,
1273 ImageHandle,
1274 &gDiskIoComponentName,
1275 &gDiskIoComponentName2
1276 );
1277 ASSERT_EFI_ERROR (Status);
1278
1279 return Status;
1280 }