• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   The SdDxe driver is used to manage the SD memory card device.
3 
4   It produces BlockIo and BlockIo2 protocols to allow upper layer
5   access the SD memory card device.
6 
7   Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
8   This program and the accompanying materials
9   are licensed and made available under the terms and conditions of the BSD License
10   which accompanies this distribution.  The full text of the license may be found at
11   http://opensource.org/licenses/bsd-license.php
12 
13   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 
16 **/
17 
18 #include "SdDxe.h"
19 
20 //
21 // SdDxe Driver Binding Protocol Instance
22 //
23 EFI_DRIVER_BINDING_PROTOCOL gSdDxeDriverBinding = {
24   SdDxeDriverBindingSupported,
25   SdDxeDriverBindingStart,
26   SdDxeDriverBindingStop,
27   0x10,
28   NULL,
29   NULL
30 };
31 
32 //
33 // Template for SD_DEVICE data structure.
34 //
35 SD_DEVICE mSdDeviceTemplate = {
36   SD_DEVICE_SIGNATURE,         // Signature
37   NULL,                        // Handle
38   NULL,                        // DevicePath
39   0xFF,                        // Slot
40   FALSE,                       // SectorAddressing
41   {                            // BlockIo
42     EFI_BLOCK_IO_PROTOCOL_REVISION,
43     NULL,
44     SdReset,
45     SdReadBlocks,
46     SdWriteBlocks,
47     SdFlushBlocks
48   },
49   {                            // BlockIo2
50     NULL,
51     SdResetEx,
52     SdReadBlocksEx,
53     SdWriteBlocksEx,
54     SdFlushBlocksEx
55   },
56   {                            // BlockMedia
57     0,                         // MediaId
58     FALSE,                     // RemovableMedia
59     TRUE,                      // MediaPresent
60     FALSE,                     // LogicPartition
61     FALSE,                     // ReadOnly
62     FALSE,                     // WritingCache
63     0x200,                     // BlockSize
64     0,                         // IoAlign
65     0                          // LastBlock
66   },
67   {                            // EraseBlock
68     EFI_ERASE_BLOCK_PROTOCOL_REVISION,
69     1,
70     SdEraseBlocks
71   },
72   {                            // Queue
73     NULL,
74     NULL
75   },
76   {                            // Csd
77     0,
78   },
79   {                            // Cid
80     0,
81   },
82   NULL,                        // ControllerNameTable
83   {                            // ModelName
84     0,
85   },
86   NULL                         // Private
87 };
88 
89 /**
90   Decode and print SD CSD Register content.
91 
92   @param[in] Csd           Pointer to SD_CSD data structure.
93 
94   @retval EFI_SUCCESS      The function completed successfully
95 **/
96 EFI_STATUS
DumpCsd(IN SD_CSD * Csd)97 DumpCsd (
98   IN SD_CSD  *Csd
99   )
100 {
101   SD_CSD2 *Csd2;
102 
103   DEBUG((DEBUG_INFO, "== Dump Sd Csd Register==\n"));
104   DEBUG((DEBUG_INFO, "  CSD structure                    0x%x\n", Csd->CsdStructure));
105   DEBUG((DEBUG_INFO, "  Data read access-time 1          0x%x\n", Csd->Taac));
106   DEBUG((DEBUG_INFO, "  Data read access-time 2          0x%x\n", Csd->Nsac));
107   DEBUG((DEBUG_INFO, "  Max. bus clock frequency         0x%x\n", Csd->TranSpeed));
108   DEBUG((DEBUG_INFO, "  Device command classes           0x%x\n", Csd->Ccc));
109   DEBUG((DEBUG_INFO, "  Max. read data block length      0x%x\n", Csd->ReadBlLen));
110   DEBUG((DEBUG_INFO, "  Partial blocks for read allowed  0x%x\n", Csd->ReadBlPartial));
111   DEBUG((DEBUG_INFO, "  Write block misalignment         0x%x\n", Csd->WriteBlkMisalign));
112   DEBUG((DEBUG_INFO, "  Read block misalignment          0x%x\n", Csd->ReadBlkMisalign));
113   DEBUG((DEBUG_INFO, "  DSR implemented                  0x%x\n", Csd->DsrImp));
114   if (Csd->CsdStructure == 0) {
115     DEBUG((DEBUG_INFO, "  Device size                      0x%x\n", Csd->CSizeLow | (Csd->CSizeHigh << 2)));
116     DEBUG((DEBUG_INFO, "  Max. read current @ VDD min      0x%x\n", Csd->VddRCurrMin));
117     DEBUG((DEBUG_INFO, "  Max. read current @ VDD max      0x%x\n", Csd->VddRCurrMax));
118     DEBUG((DEBUG_INFO, "  Max. write current @ VDD min     0x%x\n", Csd->VddWCurrMin));
119     DEBUG((DEBUG_INFO, "  Max. write current @ VDD max     0x%x\n", Csd->VddWCurrMax));
120   } else {
121     Csd2 = (SD_CSD2*)(VOID*)Csd;
122     DEBUG((DEBUG_INFO, "  Device size                      0x%x\n", Csd2->CSizeLow | (Csd->CSizeHigh << 16)));
123   }
124   DEBUG((DEBUG_INFO, "  Erase sector size                0x%x\n", Csd->SectorSize));
125   DEBUG((DEBUG_INFO, "  Erase single block enable        0x%x\n", Csd->EraseBlkEn));
126   DEBUG((DEBUG_INFO, "  Write protect group size         0x%x\n", Csd->WpGrpSize));
127   DEBUG((DEBUG_INFO, "  Write protect group enable       0x%x\n", Csd->WpGrpEnable));
128   DEBUG((DEBUG_INFO, "  Write speed factor               0x%x\n", Csd->R2WFactor));
129   DEBUG((DEBUG_INFO, "  Max. write data block length     0x%x\n", Csd->WriteBlLen));
130   DEBUG((DEBUG_INFO, "  Partial blocks for write allowed 0x%x\n", Csd->WriteBlPartial));
131   DEBUG((DEBUG_INFO, "  File format group                0x%x\n", Csd->FileFormatGrp));
132   DEBUG((DEBUG_INFO, "  Copy flag (OTP)                  0x%x\n", Csd->Copy));
133   DEBUG((DEBUG_INFO, "  Permanent write protection       0x%x\n", Csd->PermWriteProtect));
134   DEBUG((DEBUG_INFO, "  Temporary write protection       0x%x\n", Csd->TmpWriteProtect));
135   DEBUG((DEBUG_INFO, "  File format                      0x%x\n", Csd->FileFormat));
136 
137   return EFI_SUCCESS;
138 }
139 
140 /**
141   Get SD device model name.
142 
143   @param[in, out] Device   The pointer to the SD_DEVICE data structure.
144   @param[in]      Cid      Pointer to SD_CID data structure.
145 
146   @retval EFI_SUCCESS      The function completed successfully
147 
148 **/
149 EFI_STATUS
GetSdModelName(IN OUT SD_DEVICE * Device,IN SD_CID * Cid)150 GetSdModelName (
151   IN OUT SD_DEVICE         *Device,
152   IN     SD_CID            *Cid
153   )
154 {
155   CHAR8  String[SD_MODEL_NAME_MAX_LEN];
156 
157   ZeroMem (String, sizeof (String));
158   CopyMem (String, Cid->OemId, sizeof (Cid->OemId));
159   String[sizeof (Cid->OemId)] = ' ';
160   CopyMem (String + sizeof (Cid->OemId) + 1, Cid->ProductName, sizeof (Cid->ProductName));
161   String[sizeof (Cid->OemId) + sizeof (Cid->ProductName)] = ' ';
162   CopyMem (String + sizeof (Cid->OemId) + sizeof (Cid->ProductName) + 1, Cid->ProductSerialNumber, sizeof (Cid->ProductSerialNumber));
163 
164   AsciiStrToUnicodeStrS (String, Device->ModelName, sizeof (Device->ModelName) / sizeof (Device->ModelName[0]));
165 
166   return EFI_SUCCESS;
167 }
168 
169 /**
170   Discover user area partition in the SD device.
171 
172   @param[in] Device          The pointer to the SD_DEVICE data structure.
173 
174   @retval EFI_SUCCESS        The user area partition in the SD device is successfully identified.
175   @return Others             Some error occurs when identifying the user area.
176 
177 **/
178 EFI_STATUS
DiscoverUserArea(IN SD_DEVICE * Device)179 DiscoverUserArea (
180   IN SD_DEVICE             *Device
181   )
182 {
183   EFI_STATUS                        Status;
184   SD_CSD                            *Csd;
185   SD_CSD2                           *Csd2;
186   SD_CID                            *Cid;
187   UINT64                            Capacity;
188   UINT32                            DevStatus;
189   UINT16                            Rca;
190   UINT32                            CSize;
191   UINT32                            CSizeMul;
192   UINT32                            ReadBlLen;
193 
194   //
195   // Deselect the device to force it enter stby mode.
196   // Note here we don't judge return status as some SD devices return
197   // error but the state has been stby.
198   //
199   SdSelect (Device, 0);
200 
201   Status = SdSetRca (Device, &Rca);
202   if (EFI_ERROR (Status)) {
203     DEBUG ((EFI_D_ERROR, "DiscoverUserArea(): Assign new Rca = 0x%x fails with %r\n", Rca, Status));
204     return Status;
205   }
206 
207   Csd    = &Device->Csd;
208   Status = SdGetCsd (Device, Rca, Csd);
209   if (EFI_ERROR (Status)) {
210     return Status;
211   }
212   DumpCsd (Csd);
213 
214   Cid    = &Device->Cid;
215   Status = SdGetCid (Device, Rca, Cid);
216   if (EFI_ERROR (Status)) {
217     return Status;
218   }
219   GetSdModelName (Device, Cid);
220 
221   Status = SdSelect (Device, Rca);
222   if (EFI_ERROR (Status)) {
223     DEBUG ((EFI_D_ERROR, "DiscoverUserArea(): Reselect the device 0x%x fails with %r\n", Rca, Status));
224     return Status;
225   }
226 
227   Status = SdSendStatus (Device, Rca, &DevStatus);
228   if (EFI_ERROR (Status)) {
229     return Status;
230   }
231 
232   if (Csd->CsdStructure == 0) {
233     Device->SectorAddressing = FALSE;
234     CSize     = (Csd->CSizeHigh << 2 | Csd->CSizeLow) + 1;
235     CSizeMul  = (1 << (Csd->CSizeMul + 2));
236     ReadBlLen = (1 << (Csd->ReadBlLen));
237     Capacity  = MultU64x32 (MultU64x32 ((UINT64)CSize, CSizeMul), ReadBlLen);
238   } else {
239     Device->SectorAddressing = TRUE;
240     Csd2      = (SD_CSD2*)(VOID*)Csd;
241     CSize     = (Csd2->CSizeHigh << 16 | Csd2->CSizeLow) + 1;
242     Capacity  = MultU64x32 ((UINT64)CSize, SIZE_512KB);
243   }
244 
245   Device->BlockIo.Media               = &Device->BlockMedia;
246   Device->BlockIo2.Media              = &Device->BlockMedia;
247   Device->BlockMedia.IoAlign          = Device->Private->PassThru->IoAlign;
248   Device->BlockMedia.BlockSize        = 0x200;
249   Device->BlockMedia.LastBlock        = 0x00;
250   Device->BlockMedia.RemovableMedia   = TRUE;
251   Device->BlockMedia.MediaPresent     = TRUE;
252   Device->BlockMedia.LogicalPartition = FALSE;
253   Device->BlockMedia.LastBlock        = DivU64x32 (Capacity, Device->BlockMedia.BlockSize) - 1;
254 
255   if (Csd->EraseBlkEn) {
256     Device->EraseBlock.EraseLengthGranularity = 1;
257   } else {
258     Device->EraseBlock.EraseLengthGranularity = (Csd->SectorSize + 1) * (1 << (Csd->WriteBlLen - 9));
259   }
260 
261   return Status;
262 }
263 
264 /**
265   Scan SD Bus to discover the device.
266 
267   @param[in]  Private             The SD driver private data structure.
268   @param[in]  Slot                The slot number to check device present.
269 
270   @retval EFI_SUCCESS             Successfully to discover the device and attach
271                                   SdMmcIoProtocol to it.
272   @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack
273                                   of resources.
274   @retval EFI_ALREADY_STARTED     The device was discovered before.
275   @retval Others                  Fail to discover the device.
276 
277 **/
278 EFI_STATUS
279 EFIAPI
DiscoverSdDevice(IN SD_DRIVER_PRIVATE_DATA * Private,IN UINT8 Slot)280 DiscoverSdDevice (
281   IN  SD_DRIVER_PRIVATE_DATA      *Private,
282   IN  UINT8                       Slot
283   )
284 {
285   EFI_STATUS                      Status;
286   SD_DEVICE                       *Device;
287   EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
288   EFI_DEVICE_PATH_PROTOCOL        *NewDevicePath;
289   EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath;
290   EFI_HANDLE                      DeviceHandle;
291   EFI_SD_MMC_PASS_THRU_PROTOCOL   *PassThru;
292 
293   Device              = NULL;
294   DevicePath          = NULL;
295   NewDevicePath       = NULL;
296   RemainingDevicePath = NULL;
297   PassThru = Private->PassThru;
298 
299   //
300   // Build Device Path
301   //
302   Status = PassThru->BuildDevicePath (
303                        PassThru,
304                        Slot,
305                        &DevicePath
306                        );
307   if (EFI_ERROR(Status)) {
308     return Status;
309   }
310 
311   if (DevicePath->SubType != MSG_SD_DP) {
312     Status = EFI_UNSUPPORTED;
313     goto Error;
314   }
315 
316   NewDevicePath = AppendDevicePathNode (
317                     Private->ParentDevicePath,
318                     DevicePath
319                     );
320 
321   if (NewDevicePath == NULL) {
322     Status = EFI_OUT_OF_RESOURCES;
323     goto Error;
324   }
325 
326   DeviceHandle = NULL;
327   RemainingDevicePath = NewDevicePath;
328   Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);
329   if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) {
330     //
331     // The device has been started, directly return to fast boot.
332     //
333     Status = EFI_ALREADY_STARTED;
334     goto Error;
335   }
336 
337   //
338   // Allocate buffer to store SD_DEVICE private data.
339   //
340   Device = AllocateCopyPool (sizeof (SD_DEVICE), &mSdDeviceTemplate);
341   if (Device == NULL) {
342     Status = EFI_OUT_OF_RESOURCES;
343     goto Error;
344   }
345 
346   Device->DevicePath = NewDevicePath;
347   Device->Slot       = Slot;
348   Device->Private    = Private;
349   InitializeListHead (&Device->Queue);
350 
351   //
352   // Expose user area in the Sd memory card to upper layer.
353   //
354   Status = DiscoverUserArea (Device);
355   if (EFI_ERROR(Status)) {
356     goto Error;
357   }
358 
359   Device->ControllerNameTable = NULL;
360   AddUnicodeString2 (
361     "eng",
362     gSdDxeComponentName.SupportedLanguages,
363     &Device->ControllerNameTable,
364     Device->ModelName,
365     TRUE
366     );
367   AddUnicodeString2 (
368     "en",
369     gSdDxeComponentName.SupportedLanguages,
370     &Device->ControllerNameTable,
371     Device->ModelName,
372     FALSE
373     );
374 
375   Status = gBS->InstallMultipleProtocolInterfaces (
376                   &Device->Handle,
377                   &gEfiDevicePathProtocolGuid,
378                   Device->DevicePath,
379                   &gEfiBlockIoProtocolGuid,
380                   &Device->BlockIo,
381                   &gEfiBlockIo2ProtocolGuid,
382                   &Device->BlockIo2,
383                   &gEfiEraseBlockProtocolGuid,
384                   &Device->EraseBlock,
385                   NULL
386                   );
387 
388   if (!EFI_ERROR (Status)) {
389     gBS->OpenProtocol (
390            Private->Controller,
391            &gEfiSdMmcPassThruProtocolGuid,
392            (VOID **) &(Private->PassThru),
393            Private->DriverBindingHandle,
394            Device->Handle,
395            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
396            );
397   }
398 
399 Error:
400   FreePool (DevicePath);
401 
402   if (EFI_ERROR (Status) && (NewDevicePath != NULL)) {
403     FreePool (NewDevicePath);
404   }
405 
406   if (EFI_ERROR (Status) && (Device != NULL)) {
407     FreePool (Device);
408   }
409 
410   return Status;
411 }
412 
413 /**
414   Tests to see if this driver supports a given controller. If a child device is provided,
415   it further tests to see if this driver supports creating a handle for the specified child device.
416 
417   This function checks to see if the driver specified by This supports the device specified by
418   ControllerHandle. Drivers will typically use the device path attached to
419   ControllerHandle and/or the services from the bus I/O abstraction attached to
420   ControllerHandle to determine if the driver supports ControllerHandle. This function
421   may be called many times during platform initialization. In order to reduce boot times, the tests
422   performed by this function must be very small, and take as little time as possible to execute. This
423   function must not change the state of any hardware devices, and this function must be aware that the
424   device specified by ControllerHandle may already be managed by the same driver or a
425   different driver. This function must match its calls to AllocatePages() with FreePages(),
426   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
427   Since ControllerHandle may have been previously started by the same driver, if a protocol is
428   already in the opened state, then it must not be closed with CloseProtocol(). This is required
429   to guarantee the state of ControllerHandle is not modified by this function.
430 
431   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
432   @param[in]  ControllerHandle     The handle of the controller to test. This handle
433                                    must support a protocol interface that supplies
434                                    an I/O abstraction to the driver.
435   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
436                                    parameter is ignored by device drivers, and is optional for bus
437                                    drivers. For bus drivers, if this parameter is not NULL, then
438                                    the bus driver must determine if the bus controller specified
439                                    by ControllerHandle and the child controller specified
440                                    by RemainingDevicePath are both supported by this
441                                    bus driver.
442 
443   @retval EFI_SUCCESS              The device specified by ControllerHandle and
444                                    RemainingDevicePath is supported by the driver specified by This.
445   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
446                                    RemainingDevicePath is already being managed by the driver
447                                    specified by This.
448   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
449                                    RemainingDevicePath is already being managed by a different
450                                    driver or an application that requires exclusive access.
451                                    Currently not implemented.
452   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
453                                    RemainingDevicePath is not supported by the driver specified by This.
454 **/
455 EFI_STATUS
456 EFIAPI
SdDxeDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)457 SdDxeDriverBindingSupported (
458   IN EFI_DRIVER_BINDING_PROTOCOL   *This,
459   IN EFI_HANDLE                    Controller,
460   IN EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath
461   )
462 {
463   EFI_STATUS                       Status;
464   EFI_DEVICE_PATH_PROTOCOL         *ParentDevicePath;
465   EFI_SD_MMC_PASS_THRU_PROTOCOL    *PassThru;
466   UINT8                            Slot;
467 
468   //
469   // Test EFI_SD_MMC_PASS_THRU_PROTOCOL on the controller handle.
470   //
471   Status = gBS->OpenProtocol (
472                   Controller,
473                   &gEfiSdMmcPassThruProtocolGuid,
474                   (VOID**) &PassThru,
475                   This->DriverBindingHandle,
476                   Controller,
477                   EFI_OPEN_PROTOCOL_BY_DRIVER
478                   );
479 
480   if (Status == EFI_ALREADY_STARTED) {
481     return EFI_SUCCESS;
482   }
483 
484   if (EFI_ERROR (Status)) {
485     return Status;
486   }
487 
488   //
489   // Test RemainingDevicePath is valid or not.
490   //
491   if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {
492     Status = PassThru->GetSlotNumber (PassThru, RemainingDevicePath, &Slot);
493     if (EFI_ERROR (Status)) {
494       //
495       // Close the I/O Abstraction(s) used to perform the supported test
496       //
497       gBS->CloseProtocol (
498              Controller,
499              &gEfiSdMmcPassThruProtocolGuid,
500              This->DriverBindingHandle,
501              Controller
502              );
503       return Status;
504     }
505   }
506 
507   //
508   // Close the I/O Abstraction(s) used to perform the supported test
509   //
510   gBS->CloseProtocol (
511          Controller,
512          &gEfiSdMmcPassThruProtocolGuid,
513          This->DriverBindingHandle,
514          Controller
515          );
516 
517   //
518   // Open the EFI Device Path protocol needed to perform the supported test
519   //
520   Status = gBS->OpenProtocol (
521                   Controller,
522                   &gEfiDevicePathProtocolGuid,
523                   (VOID **) &ParentDevicePath,
524                   This->DriverBindingHandle,
525                   Controller,
526                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
527                   );
528   return Status;
529 }
530 
531 /**
532   Starts a device controller or a bus controller.
533 
534   The Start() function is designed to be invoked from the EFI boot service ConnectController().
535   As a result, much of the error checking on the parameters to Start() has been moved into this
536   common boot service. It is legal to call Start() from other locations,
537   but the following calling restrictions must be followed or the system behavior will not be deterministic.
538   1. ControllerHandle must be a valid EFI_HANDLE.
539   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
540      EFI_DEVICE_PATH_PROTOCOL.
541   3. Prior to calling Start(), the Supported() function for the driver specified by This must
542      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
543 
544   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
545   @param[in]  ControllerHandle     The handle of the controller to start. This handle
546                                    must support a protocol interface that supplies
547                                    an I/O abstraction to the driver.
548   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
549                                    parameter is ignored by device drivers, and is optional for bus
550                                    drivers. For a bus driver, if this parameter is NULL, then handles
551                                    for all the children of Controller are created by this driver.
552                                    If this parameter is not NULL and the first Device Path Node is
553                                    not the End of Device Path Node, then only the handle for the
554                                    child device specified by the first Device Path Node of
555                                    RemainingDevicePath is created by this driver.
556                                    If the first Device Path Node of RemainingDevicePath is
557                                    the End of Device Path Node, no child handle is created by this
558                                    driver.
559 
560   @retval EFI_SUCCESS              The device was started.
561   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
562   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
563   @retval Others                   The driver failded to start the device.
564 
565 **/
566 EFI_STATUS
567 EFIAPI
SdDxeDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)568 SdDxeDriverBindingStart (
569   IN EFI_DRIVER_BINDING_PROTOCOL   *This,
570   IN EFI_HANDLE                    Controller,
571   IN EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath
572   )
573 {
574   EFI_STATUS                       Status;
575   EFI_SD_MMC_PASS_THRU_PROTOCOL    *PassThru;
576   EFI_DEVICE_PATH_PROTOCOL         *ParentDevicePath;
577   SD_DRIVER_PRIVATE_DATA           *Private;
578   UINT8                            Slot;
579 
580   Private  = NULL;
581   PassThru = NULL;
582   Status = gBS->OpenProtocol (
583                   Controller,
584                   &gEfiSdMmcPassThruProtocolGuid,
585                   (VOID **) &PassThru,
586                   This->DriverBindingHandle,
587                   Controller,
588                   EFI_OPEN_PROTOCOL_BY_DRIVER
589                   );
590   if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
591     return Status;
592   }
593 
594   //
595   // Check EFI_ALREADY_STARTED to reuse the original SD_DRIVER_PRIVATE_DATA.
596   //
597   if (Status != EFI_ALREADY_STARTED) {
598     Private = AllocateZeroPool (sizeof (SD_DRIVER_PRIVATE_DATA));
599     if (Private == NULL) {
600       Status = EFI_OUT_OF_RESOURCES;
601       goto Error;
602     }
603 
604     Status = gBS->OpenProtocol (
605                     Controller,
606                     &gEfiDevicePathProtocolGuid,
607                     (VOID **) &ParentDevicePath,
608                     This->DriverBindingHandle,
609                     Controller,
610                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
611                     );
612     ASSERT_EFI_ERROR (Status);
613     Private->PassThru            = PassThru;
614     Private->Controller          = Controller;
615     Private->ParentDevicePath    = ParentDevicePath;
616     Private->DriverBindingHandle = This->DriverBindingHandle;
617 
618     Status = gBS->InstallProtocolInterface (
619                     &Controller,
620                     &gEfiCallerIdGuid,
621                     EFI_NATIVE_INTERFACE,
622                     Private
623                     );
624     if (EFI_ERROR (Status)) {
625       goto Error;
626     }
627   } else {
628     Status = gBS->OpenProtocol (
629                     Controller,
630                     &gEfiCallerIdGuid,
631                     (VOID **) &Private,
632                     This->DriverBindingHandle,
633                     Controller,
634                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
635                     );
636     if (EFI_ERROR (Status)) {
637       goto Error;
638     }
639   }
640 
641   if (RemainingDevicePath == NULL) {
642     Slot = 0xFF;
643     while (TRUE) {
644       Status = PassThru->GetNextSlot (PassThru, &Slot);
645       if (EFI_ERROR (Status)) {
646         //
647         // Cannot find more legal slots.
648         //
649         Status = EFI_SUCCESS;
650         break;
651       }
652 
653       Status = DiscoverSdDevice (Private, Slot);
654       if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
655         break;
656       }
657     }
658   } else if (!IsDevicePathEnd (RemainingDevicePath)) {
659     Status = PassThru->GetSlotNumber (PassThru, RemainingDevicePath, &Slot);
660     if (!EFI_ERROR (Status)) {
661       Status = DiscoverSdDevice (Private, Slot);
662     }
663   }
664 
665 Error:
666   if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
667     gBS->CloseProtocol (
668            Controller,
669            &gEfiSdMmcPassThruProtocolGuid,
670            This->DriverBindingHandle,
671            Controller
672            );
673 
674     if (Private != NULL) {
675       gBS->UninstallMultipleProtocolInterfaces (
676            Controller,
677            &gEfiCallerIdGuid,
678            Private,
679            NULL
680            );
681       FreePool (Private);
682     }
683   }
684   return Status;
685 }
686 
687 /**
688   Stops a device controller or a bus controller.
689 
690   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
691   As a result, much of the error checking on the parameters to Stop() has been moved
692   into this common boot service. It is legal to call Stop() from other locations,
693   but the following calling restrictions must be followed or the system behavior will not be deterministic.
694   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
695      same driver's Start() function.
696   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
697      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
698      Start() function, and the Start() function must have called OpenProtocol() on
699      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
700 
701   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
702   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
703                                 support a bus specific I/O protocol for the driver
704                                 to use to stop the device.
705   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
706   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
707                                 if NumberOfChildren is 0.
708 
709   @retval EFI_SUCCESS           The device was stopped.
710   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
711 
712 **/
713 EFI_STATUS
714 EFIAPI
SdDxeDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)715 SdDxeDriverBindingStop (
716   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
717   IN  EFI_HANDLE                      Controller,
718   IN  UINTN                           NumberOfChildren,
719   IN  EFI_HANDLE                      *ChildHandleBuffer
720   )
721 {
722   EFI_STATUS                          Status;
723   BOOLEAN                             AllChildrenStopped;
724   UINTN                               Index;
725   SD_DRIVER_PRIVATE_DATA              *Private;
726   SD_DEVICE                           *Device;
727   EFI_SD_MMC_PASS_THRU_PROTOCOL       *PassThru;
728   EFI_BLOCK_IO2_PROTOCOL              *BlockIo2;
729   EFI_BLOCK_IO_PROTOCOL               *BlockIo;
730   LIST_ENTRY                          *Link;
731   LIST_ENTRY                          *NextLink;
732   SD_REQUEST                          *Request;
733   EFI_TPL                             OldTpl;
734 
735   if (NumberOfChildren == 0) {
736     Status = gBS->OpenProtocol (
737                     Controller,
738                     &gEfiCallerIdGuid,
739                     (VOID **) &Private,
740                     This->DriverBindingHandle,
741                     Controller,
742                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
743                     );
744     if (EFI_ERROR (Status)) {
745       return EFI_DEVICE_ERROR;
746     }
747 
748     gBS->UninstallProtocolInterface (
749           Controller,
750           &gEfiCallerIdGuid,
751           Private
752           );
753     gBS->CloseProtocol (
754           Controller,
755           &gEfiSdMmcPassThruProtocolGuid,
756           This->DriverBindingHandle,
757           Controller
758           );
759 
760     FreePool (Private);
761 
762     return EFI_SUCCESS;
763   }
764 
765   AllChildrenStopped = TRUE;
766 
767   for (Index = 0; Index < NumberOfChildren; Index++) {
768     BlockIo  = NULL;
769     BlockIo2 = NULL;
770     Status = gBS->OpenProtocol (
771                     ChildHandleBuffer[Index],
772                     &gEfiBlockIoProtocolGuid,
773                     (VOID **) &BlockIo,
774                     This->DriverBindingHandle,
775                     Controller,
776                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
777                     );
778     if (EFI_ERROR (Status)) {
779       Status = gBS->OpenProtocol (
780                       ChildHandleBuffer[Index],
781                       &gEfiBlockIo2ProtocolGuid,
782                       (VOID **) &BlockIo2,
783                       This->DriverBindingHandle,
784                       Controller,
785                       EFI_OPEN_PROTOCOL_GET_PROTOCOL
786                       );
787       if (EFI_ERROR (Status)) {
788         AllChildrenStopped = FALSE;
789         continue;
790       }
791     }
792 
793     if (BlockIo != NULL) {
794       Device = SD_DEVICE_DATA_FROM_BLKIO (BlockIo);
795     } else {
796       ASSERT (BlockIo2 != NULL);
797       Device = SD_DEVICE_DATA_FROM_BLKIO2 (BlockIo2);
798     }
799 
800     //
801     // Free all on-going async tasks.
802     //
803     OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
804     for (Link = GetFirstNode (&Device->Queue);
805          !IsNull (&Device->Queue, Link);
806          Link = NextLink) {
807       NextLink = GetNextNode (&Device->Queue, Link);
808       RemoveEntryList (Link);
809 
810       Request = SD_REQUEST_FROM_LINK (Link);
811 
812       gBS->CloseEvent (Request->Event);
813       Request->Token->TransactionStatus = EFI_ABORTED;
814 
815       if (Request->IsEnd) {
816         gBS->SignalEvent (Request->Token->Event);
817       }
818 
819       FreePool (Request);
820     }
821     gBS->RestoreTPL (OldTpl);
822 
823     //
824     // Close the child handle
825     //
826     Status = gBS->CloseProtocol (
827                     Controller,
828                     &gEfiSdMmcPassThruProtocolGuid,
829                     This->DriverBindingHandle,
830                     ChildHandleBuffer[Index]
831                     );
832 
833     Status = gBS->UninstallMultipleProtocolInterfaces (
834                     ChildHandleBuffer[Index],
835                     &gEfiDevicePathProtocolGuid,
836                     Device->DevicePath,
837                     &gEfiBlockIoProtocolGuid,
838                     &Device->BlockIo,
839                     &gEfiBlockIo2ProtocolGuid,
840                     &Device->BlockIo2,
841                     &gEfiEraseBlockProtocolGuid,
842                     &Device->EraseBlock,
843                     NULL
844                     );
845     if (EFI_ERROR (Status)) {
846       AllChildrenStopped = FALSE;
847         gBS->OpenProtocol (
848                Controller,
849                &gEfiSdMmcPassThruProtocolGuid,
850                (VOID **)&PassThru,
851                This->DriverBindingHandle,
852                ChildHandleBuffer[Index],
853                EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
854                );
855     } else {
856       FreePool (Device->DevicePath);
857       FreeUnicodeStringTable (Device->ControllerNameTable);
858       FreePool (Device);
859     }
860   }
861 
862   if (!AllChildrenStopped) {
863     return EFI_DEVICE_ERROR;
864   }
865 
866   return EFI_SUCCESS;
867 }
868 
869 /**
870   The user Entry Point for module SdDxe. The user code starts with this function.
871 
872   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
873   @param[in] SystemTable    A pointer to the EFI System Table.
874 
875   @retval EFI_SUCCESS       The entry point is executed successfully.
876   @retval other             Some errors occur when executing this entry point.
877 
878 **/
879 EFI_STATUS
880 EFIAPI
InitializeSdDxe(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)881 InitializeSdDxe (
882   IN EFI_HANDLE           ImageHandle,
883   IN EFI_SYSTEM_TABLE     *SystemTable
884   )
885 {
886   EFI_STATUS              Status;
887 
888   //
889   // Install driver model protocol(s).
890   //
891   Status = EfiLibInstallDriverBindingComponentName2 (
892              ImageHandle,
893              SystemTable,
894              &gSdDxeDriverBinding,
895              ImageHandle,
896              &gSdDxeComponentName,
897              &gSdDxeComponentName2
898              );
899   ASSERT_EFI_ERROR (Status);
900 
901   return Status;
902 }
903 
904