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

« back to all changes in this revision

Viewing changes to src/VBox/Devices/EFI/Firmware/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyIde.c

  • Committer: Package Import Robot
  • Author(s): Gianfranco Costamagna
  • Date: 2016-02-23 14:28:26 UTC
  • Revision ID: package-import@ubuntu.com-20160223142826-bdu69el2z6wa2a44
Tags: upstream-4.3.36-dfsg
ImportĀ upstreamĀ versionĀ 4.3.36-dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** @file
 
2
  Collect IDE information from Native EFI Driver
 
3
 
 
4
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
 
5
 
 
6
This program and the accompanying materials
 
7
are licensed and made available under the terms and conditions
 
8
of the BSD License which accompanies this distribution.  The
 
9
full text of the license may be found at
 
10
http://opensource.org/licenses/bsd-license.php
 
11
 
 
12
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 
13
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
14
 
 
15
**/
 
16
 
 
17
#include "LegacyBiosInterface.h"
 
18
 
 
19
BOOLEAN mIdeDataBuiltFlag = FALSE;
 
20
 
 
21
/**
 
22
  Collect IDE Inquiry data from the IDE disks
 
23
 
 
24
  @param  Private        Legacy BIOS Instance data
 
25
  @param  HddInfo        Hdd Information
 
26
  @param  Flag           Reconnect IdeController or not
 
27
 
 
28
  @retval EFI_SUCCESS    It should always work.
 
29
 
 
30
**/
 
31
EFI_STATUS
 
32
LegacyBiosBuildIdeData (
 
33
  IN  LEGACY_BIOS_INSTANCE      *Private,
 
34
  IN  HDD_INFO                  **HddInfo,
 
35
  IN  UINT16                    Flag
 
36
  )
 
37
{
 
38
  EFI_STATUS                Status;
 
39
  EFI_HANDLE                IdeController;
 
40
  UINTN                     HandleCount;
 
41
  EFI_HANDLE                *HandleBuffer;
 
42
  UINTN                     Index;
 
43
  EFI_DISK_INFO_PROTOCOL    *DiskInfo;
 
44
  UINT32                    IdeChannel;
 
45
  UINT32                    IdeDevice;
 
46
  UINT32                    Size;
 
47
  UINT8                     *InquiryData;
 
48
  UINT32                    InquiryDataSize;
 
49
  HDD_INFO                  *LocalHddInfo;
 
50
  UINT32                    PciIndex;
 
51
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 
52
  EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode;
 
53
  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePathNode;
 
54
  PCI_DEVICE_PATH           *PciDevicePath;
 
55
 
 
56
  //
 
57
  // Only build data once
 
58
  // We have a problem with GetBbsInfo in that it can be invoked two
 
59
  // places. Once in BDS, when all EFI drivers are connected and once in
 
60
  // LegacyBoot after all EFI drivers are disconnected causing this routine
 
61
  // to hang. In LegacyBoot this function is also called before EFI drivers
 
62
  // are disconnected.
 
63
  // Cases covered
 
64
  //    GetBbsInfo invoked in BDS. Both invocations in LegacyBoot ignored.
 
65
  //    GetBbsInfo not invoked in BDS. First invocation of this function
 
66
  //       proceeds normally and second via GetBbsInfo ignored.
 
67
  //
 
68
  PciDevicePath = NULL;
 
69
  LocalHddInfo  = *HddInfo;
 
70
  Status = Private->LegacyBiosPlatform->GetPlatformHandle (
 
71
                                          Private->LegacyBiosPlatform,
 
72
                                          EfiGetPlatformIdeHandle,
 
73
                                          0,
 
74
                                          &HandleBuffer,
 
75
                                          &HandleCount,
 
76
                                          (VOID *) &LocalHddInfo
 
77
                                          );
 
78
  if (!EFI_ERROR (Status)) {
 
79
    IdeController = HandleBuffer[0];    
 
80
    //
 
81
    // Force IDE drive spin up!
 
82
    //
 
83
    if (Flag != 0) {
 
84
      gBS->DisconnectController (
 
85
            IdeController,
 
86
            NULL,
 
87
            NULL
 
88
            );
 
89
    }
 
90
 
 
91
    gBS->ConnectController (IdeController, NULL, NULL, FALSE);
 
92
 
 
93
    //
 
94
    // Do GetIdeHandle twice since disconnect/reconnect will switch to native mode
 
95
    // And GetIdeHandle will switch to Legacy mode, if required.
 
96
    //
 
97
    Private->LegacyBiosPlatform->GetPlatformHandle (
 
98
                                  Private->LegacyBiosPlatform,
 
99
                                  EfiGetPlatformIdeHandle,
 
100
                                  0,
 
101
                                  &HandleBuffer,
 
102
                                  &HandleCount,
 
103
                                  (VOID *) &LocalHddInfo
 
104
                                  );
 
105
  }
 
106
 
 
107
  mIdeDataBuiltFlag = TRUE;
 
108
 
 
109
  //
 
110
  // Get Identity command from all drives
 
111
  //
 
112
  gBS->LocateHandleBuffer (
 
113
        ByProtocol,
 
114
        &gEfiDiskInfoProtocolGuid,
 
115
        NULL,
 
116
        &HandleCount,
 
117
        &HandleBuffer
 
118
        );
 
119
 
 
120
  Private->IdeDriveCount = (UINT8) HandleCount;
 
121
  for (Index = 0; Index < HandleCount; Index++) {
 
122
    Status = gBS->HandleProtocol (
 
123
                    HandleBuffer[Index],
 
124
                    &gEfiDiskInfoProtocolGuid,
 
125
                    (VOID **) &DiskInfo
 
126
                    );
 
127
    ASSERT_EFI_ERROR (Status);
 
128
 
 
129
    if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) {
 
130
      //
 
131
      //  Locate which PCI device
 
132
      //
 
133
      Status = gBS->HandleProtocol (
 
134
                      HandleBuffer[Index],
 
135
                      &gEfiDevicePathProtocolGuid,
 
136
                      (VOID *) &DevicePath
 
137
                      );
 
138
      ASSERT_EFI_ERROR (Status);
 
139
 
 
140
      DevicePathNode = DevicePath;
 
141
      while (!IsDevicePathEnd (DevicePathNode)) {
 
142
        TempDevicePathNode = NextDevicePathNode (DevicePathNode);
 
143
        if ((DevicePathType (DevicePathNode) == HARDWARE_DEVICE_PATH) &&
 
144
              ( DevicePathSubType (DevicePathNode) == HW_PCI_DP) &&
 
145
              ( DevicePathType(TempDevicePathNode) == MESSAGING_DEVICE_PATH) &&
 
146
              ( DevicePathSubType(TempDevicePathNode) == MSG_ATAPI_DP) ) {
 
147
          PciDevicePath = (PCI_DEVICE_PATH *) DevicePathNode;
 
148
          break;
 
149
        }
 
150
        DevicePathNode = NextDevicePathNode (DevicePathNode);
 
151
      }
 
152
 
 
153
      if (PciDevicePath == NULL) {
 
154
        continue;
 
155
      }
 
156
 
 
157
      //
 
158
      // Find start of PCI device in HddInfo. The assumption of the data
 
159
      // structure is 2 controllers(channels) per PCI device and each
 
160
      // controller can have 2 drives(devices).
 
161
      // HddInfo[PciIndex+0].[0] = Channel[0].Device[0] Primary Master
 
162
      // HddInfo[PciIndex+0].[1] = Channel[0].Device[1] Primary Slave
 
163
      // HddInfo[PciIndex+1].[0] = Channel[1].Device[0] Secondary Master
 
164
      // HddInfo[PciIndex+1].[1] = Channel[1].Device[1] Secondary Slave
 
165
      // @bug eventually need to pass in max number of entries
 
166
      // for end of for loop
 
167
      //
 
168
      for (PciIndex = 0; PciIndex < 8; PciIndex++) {
 
169
        if ((PciDevicePath->Device == LocalHddInfo[PciIndex].Device) &&
 
170
            (PciDevicePath->Function == LocalHddInfo[PciIndex].Function)
 
171
            ) {
 
172
          break;
 
173
        }
 
174
      }
 
175
 
 
176
      if (PciIndex == 8) {
 
177
        continue;
 
178
      }
 
179
 
 
180
      Status = DiskInfo->WhichIde (DiskInfo, &IdeChannel, &IdeDevice);
 
181
      if (!EFI_ERROR (Status)) {
 
182
        Size = sizeof (ATAPI_IDENTIFY);
 
183
        DiskInfo->Identify (
 
184
                    DiskInfo,
 
185
                    &LocalHddInfo[PciIndex + IdeChannel].IdentifyDrive[IdeDevice],
 
186
                    &Size
 
187
                    );
 
188
        if (IdeChannel == 0) {
 
189
          LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_PRIMARY;
 
190
        } else if (IdeChannel == 1) {
 
191
          LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SECONDARY;
 
192
        }
 
193
 
 
194
        InquiryData     = NULL;
 
195
        InquiryDataSize = 0;
 
196
        Status = DiskInfo->Inquiry (
 
197
                             DiskInfo,
 
198
                             NULL,
 
199
                             &InquiryDataSize
 
200
                             );
 
201
        if (Status == EFI_BUFFER_TOO_SMALL) {
 
202
          InquiryData = (UINT8 *) AllocatePool (
 
203
                                  InquiryDataSize
 
204
                                  );
 
205
          if (InquiryData != NULL) {
 
206
            Status = DiskInfo->Inquiry (
 
207
                                 DiskInfo,
 
208
                                 InquiryData,
 
209
                                 &InquiryDataSize
 
210
                                 );
 
211
          }
 
212
        } else {
 
213
          Status = EFI_DEVICE_ERROR;
 
214
        }
 
215
 
 
216
        //
 
217
        // If ATAPI device then Inquiry will pass and ATA fail.
 
218
        //
 
219
        if (!EFI_ERROR (Status)) {
 
220
          ASSERT (InquiryData != NULL);
 
221
          //
 
222
          // If IdeDevice = 0 then set master bit, else slave bit
 
223
          //
 
224
          if (IdeDevice == 0) {
 
225
            if ((InquiryData[0] & 0x1f) == 0x05) {
 
226
              LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_CDROM;
 
227
            } else if ((InquiryData[0] & 0x1f) == 0x00) {
 
228
              LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_ZIPDISK;
 
229
            }
 
230
          } else {
 
231
            if ((InquiryData[0] & 0x1f) == 0x05) {
 
232
              LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_CDROM;
 
233
            } else if ((InquiryData[0] & 0x1f) == 0x00) {
 
234
              LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_ZIPDISK;
 
235
            }
 
236
          }
 
237
          FreePool (InquiryData);
 
238
        } else {
 
239
          if (IdeDevice == 0) {
 
240
            LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_IDE;
 
241
          } else {
 
242
            LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_IDE;
 
243
          }
 
244
        }
 
245
      }
 
246
    }
 
247
  }
 
248
 
 
249
  if (HandleBuffer != NULL) {
 
250
    FreePool (HandleBuffer);
 
251
  }
 
252
 
 
253
  return EFI_SUCCESS;
 
254
}
 
255
 
 
256
 
 
257
/**
 
258
  If the IDE channel is in compatibility (legacy) mode, remove all
 
259
  PCI I/O BAR addresses from the controller.
 
260
 
 
261
  @param  IdeController  The handle of target IDE controller
 
262
 
 
263
 
 
264
**/
 
265
VOID
 
266
InitLegacyIdeController (
 
267
  IN EFI_HANDLE                        IdeController
 
268
  )
 
269
{
 
270
  EFI_PCI_IO_PROTOCOL               *PciIo;
 
271
  UINT8                             Pi;
 
272
  UINT32                            IOBarClear;
 
273
  EFI_STATUS                        Status;
 
274
 
 
275
  //
 
276
  // If the IDE channel is in compatibility (legacy) mode, remove all
 
277
  // PCI I/O BAR addresses from the controller.  Some software gets
 
278
  // confused if an IDE controller is in compatibility (legacy) mode
 
279
  // and has PCI I/O resources allocated
 
280
  //
 
281
  Status = gBS->HandleProtocol (
 
282
                  IdeController,
 
283
                  &gEfiPciIoProtocolGuid,
 
284
                  (VOID **) &PciIo
 
285
                  );
 
286
  if (!EFI_ERROR (Status)) {
 
287
    IOBarClear = 0x00;
 
288
    PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 1, &Pi);
 
289
    if ((Pi & 0x01) == 0) {
 
290
      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x10, 1, &IOBarClear);
 
291
      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x14, 1, &IOBarClear);
 
292
    }
 
293
    if ((Pi & 0x04) == 0) {
 
294
      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x18, 1, &IOBarClear);
 
295
      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1C, 1, &IOBarClear);
 
296
    }
 
297
  }
 
298
 
 
299
  return ;
 
300
}