~ubuntu-branches/ubuntu/trusty/virtualbox/trusty-proposed

« back to all changes in this revision

Viewing changes to src/VBox/Devices/EFI/Firmware2/VBoxPkg/PartitionDxe/Partition.c

  • Committer: Package Import Robot
  • Author(s): Felix Geyer
  • Date: 2013-03-07 16:38:36 UTC
  • mfrom: (1.1.13) (3.1.20 experimental)
  • Revision ID: package-import@ubuntu.com-20130307163836-p93jpbgx39tp3gb4
Tags: 4.2.8-dfsg-0ubuntu1
* New upstream release. (Closes: #691148)
  - Fixes compatibility with kernel 3.8. (Closes: #700823; LP: #1101867)
* Switch to my @debian.org email address.
* Move package to contrib as virtualbox 4.2 needs a non-free compiler to
  build the BIOS.
* Build-depend on libdevmapper-dev.
* Refresh patches.
  - Drop 36-fix-ftbfs-xserver-112.patch, cve-2012-3221.patch,
    CVE-2013-0420.patch 37-kcompat-3.6.patch and 38-kcompat-3.7.patch.
* Drop all virtualbox-ose transitional packages.
* Drop the virtualbox-fuse package as vdfuse fails to build with
  virtualbox 4.2.
* Update install files and VBox.sh.
* Bump required kbuild version to 0.1.9998svn2577.
* Fix path to VBoxCreateUSBNode.sh in virtualbox.postinst. (Closes: #700479)
* Add an init script to virtuabox-guest-x11 which loads the vboxvideo
  kernel module. The X Server 1.13 doesn't load it anymore. (Closes: #686994)
* Update man pages. (Closes: #680053)
* Add 36-python-multiarch.patch from Rico Tzschichholz to fix detection of
  python in multiarch paths using pkg-config.

Show diffs side-by-side

added added

removed removed

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