| 1 | /** @file\r |
| 2 | Platform BDS customizations.\r |
| 3 | \r |
| 4 | Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r |
| 5 | All rights reserved. This program and the accompanying materials\r |
| 6 | are licensed and made available under the terms and conditions of the BSD License\r |
| 7 | which accompanies this distribution. The full text of the license may be found at\r |
| 8 | http://opensource.org/licenses/bsd-license.php\r |
| 9 | \r |
| 10 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r |
| 11 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r |
| 12 | \r |
| 13 | **/\r |
| 14 | \r |
| 15 | #include "BdsPlatform.h"\r |
| 16 | \r |
| 17 | \r |
| 18 | //\r |
| 19 | // BDS Platform Functions\r |
| 20 | //\r |
| 21 | VOID\r |
| 22 | EFIAPI\r |
| 23 | PlatformBdsInit (\r |
| 24 | IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData\r |
| 25 | )\r |
| 26 | /*++\r |
| 27 | \r |
| 28 | Routine Description:\r |
| 29 | \r |
| 30 | Platform Bds init. Incude the platform firmware vendor, revision\r |
| 31 | and so crc check.\r |
| 32 | \r |
| 33 | Arguments:\r |
| 34 | \r |
| 35 | PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance\r |
| 36 | \r |
| 37 | Returns:\r |
| 38 | \r |
| 39 | None.\r |
| 40 | \r |
| 41 | --*/\r |
| 42 | {\r |
| 43 | DEBUG ((EFI_D_INFO, "PlatformBdsInit\n"));\r |
| 44 | }\r |
| 45 | \r |
| 46 | \r |
| 47 | EFI_STATUS\r |
| 48 | ConnectRootBridge (\r |
| 49 | VOID\r |
| 50 | )\r |
| 51 | /*++\r |
| 52 | \r |
| 53 | Routine Description:\r |
| 54 | \r |
| 55 | Connect RootBridge\r |
| 56 | \r |
| 57 | Arguments:\r |
| 58 | \r |
| 59 | None.\r |
| 60 | \r |
| 61 | Returns:\r |
| 62 | \r |
| 63 | EFI_SUCCESS - Connect RootBridge successfully.\r |
| 64 | EFI_STATUS - Connect RootBridge fail.\r |
| 65 | \r |
| 66 | --*/\r |
| 67 | {\r |
| 68 | EFI_STATUS Status;\r |
| 69 | EFI_HANDLE RootHandle;\r |
| 70 | \r |
| 71 | //\r |
| 72 | // Make all the PCI_IO protocols on PCI Seg 0 show up\r |
| 73 | //\r |
| 74 | BdsLibConnectDevicePath (gPlatformRootBridges[0]);\r |
| 75 | \r |
| 76 | Status = gBS->LocateDevicePath (\r |
| 77 | &gEfiDevicePathProtocolGuid,\r |
| 78 | &gPlatformRootBridges[0],\r |
| 79 | &RootHandle\r |
| 80 | );\r |
| 81 | if (EFI_ERROR (Status)) {\r |
| 82 | return Status;\r |
| 83 | }\r |
| 84 | \r |
| 85 | Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);\r |
| 86 | if (EFI_ERROR (Status)) {\r |
| 87 | return Status;\r |
| 88 | }\r |
| 89 | \r |
| 90 | return EFI_SUCCESS;\r |
| 91 | }\r |
| 92 | \r |
| 93 | \r |
| 94 | EFI_STATUS\r |
| 95 | PrepareLpcBridgeDevicePath (\r |
| 96 | IN EFI_HANDLE DeviceHandle\r |
| 97 | )\r |
| 98 | /*++\r |
| 99 | \r |
| 100 | Routine Description:\r |
| 101 | \r |
| 102 | Add IsaKeyboard to ConIn,\r |
| 103 | add IsaSerial to ConOut, ConIn, ErrOut.\r |
| 104 | LPC Bridge: 06 01 00\r |
| 105 | \r |
| 106 | Arguments:\r |
| 107 | \r |
| 108 | DeviceHandle - Handle of PCIIO protocol.\r |
| 109 | \r |
| 110 | Returns:\r |
| 111 | \r |
| 112 | EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.\r |
| 113 | EFI_STATUS - No LPC bridge is added.\r |
| 114 | \r |
| 115 | --*/\r |
| 116 | {\r |
| 117 | EFI_STATUS Status;\r |
| 118 | EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r |
| 119 | EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r |
| 120 | CHAR16 *DevPathStr;\r |
| 121 | \r |
| 122 | DevicePath = NULL;\r |
| 123 | Status = gBS->HandleProtocol (\r |
| 124 | DeviceHandle,\r |
| 125 | &gEfiDevicePathProtocolGuid,\r |
| 126 | (VOID*)&DevicePath\r |
| 127 | );\r |
| 128 | if (EFI_ERROR (Status)) {\r |
| 129 | return Status;\r |
| 130 | }\r |
| 131 | TempDevicePath = DevicePath;\r |
| 132 | \r |
| 133 | //\r |
| 134 | // Register Keyboard\r |
| 135 | //\r |
| 136 | DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);\r |
| 137 | \r |
| 138 | BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r |
| 139 | \r |
| 140 | //\r |
| 141 | // Register COM1\r |
| 142 | //\r |
| 143 | DevicePath = TempDevicePath;\r |
| 144 | gPnp16550ComPortDeviceNode.UID = 0;\r |
| 145 | \r |
| 146 | DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r |
| 147 | DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r |
| 148 | DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r |
| 149 | \r |
| 150 | //\r |
| 151 | // Print Device Path\r |
| 152 | //\r |
| 153 | DevPathStr = DevicePathToStr(DevicePath);\r |
| 154 | DEBUG((\r |
| 155 | EFI_D_INFO,\r |
| 156 | "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r |
| 157 | __LINE__,\r |
| 158 | gPnp16550ComPortDeviceNode.UID + 1,\r |
| 159 | DevPathStr\r |
| 160 | ));\r |
| 161 | FreePool(DevPathStr);\r |
| 162 | \r |
| 163 | BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r |
| 164 | BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r |
| 165 | BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r |
| 166 | \r |
| 167 | //\r |
| 168 | // Register COM2\r |
| 169 | //\r |
| 170 | DevicePath = TempDevicePath;\r |
| 171 | gPnp16550ComPortDeviceNode.UID = 1;\r |
| 172 | \r |
| 173 | DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r |
| 174 | DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r |
| 175 | DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r |
| 176 | \r |
| 177 | //\r |
| 178 | // Print Device Path\r |
| 179 | //\r |
| 180 | DevPathStr = DevicePathToStr(DevicePath);\r |
| 181 | DEBUG((\r |
| 182 | EFI_D_INFO,\r |
| 183 | "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r |
| 184 | __LINE__,\r |
| 185 | gPnp16550ComPortDeviceNode.UID + 1,\r |
| 186 | DevPathStr\r |
| 187 | ));\r |
| 188 | FreePool(DevPathStr);\r |
| 189 | \r |
| 190 | BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r |
| 191 | BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r |
| 192 | BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r |
| 193 | \r |
| 194 | return EFI_SUCCESS;\r |
| 195 | }\r |
| 196 | \r |
| 197 | EFI_STATUS\r |
| 198 | GetGopDevicePath (\r |
| 199 | IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,\r |
| 200 | OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath\r |
| 201 | )\r |
| 202 | {\r |
| 203 | UINTN Index;\r |
| 204 | EFI_STATUS Status;\r |
| 205 | EFI_HANDLE PciDeviceHandle;\r |
| 206 | EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r |
| 207 | EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;\r |
| 208 | UINTN GopHandleCount;\r |
| 209 | EFI_HANDLE *GopHandleBuffer;\r |
| 210 | \r |
| 211 | if (PciDevicePath == NULL || GopDevicePath == NULL) {\r |
| 212 | return EFI_INVALID_PARAMETER;\r |
| 213 | }\r |
| 214 | \r |
| 215 | //\r |
| 216 | // Initialize the GopDevicePath to be PciDevicePath\r |
| 217 | //\r |
| 218 | *GopDevicePath = PciDevicePath;\r |
| 219 | TempPciDevicePath = PciDevicePath;\r |
| 220 | \r |
| 221 | Status = gBS->LocateDevicePath (\r |
| 222 | &gEfiDevicePathProtocolGuid,\r |
| 223 | &TempPciDevicePath,\r |
| 224 | &PciDeviceHandle\r |
| 225 | );\r |
| 226 | if (EFI_ERROR (Status)) {\r |
| 227 | return Status;\r |
| 228 | }\r |
| 229 | \r |
| 230 | //\r |
| 231 | // Try to connect this handle, so that GOP dirver could start on this\r |
| 232 | // device and create child handles with GraphicsOutput Protocol installed\r |
| 233 | // on them, then we get device paths of these child handles and select\r |
| 234 | // them as possible console device.\r |
| 235 | //\r |
| 236 | gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);\r |
| 237 | \r |
| 238 | Status = gBS->LocateHandleBuffer (\r |
| 239 | ByProtocol,\r |
| 240 | &gEfiGraphicsOutputProtocolGuid,\r |
| 241 | NULL,\r |
| 242 | &GopHandleCount,\r |
| 243 | &GopHandleBuffer\r |
| 244 | );\r |
| 245 | if (!EFI_ERROR (Status)) {\r |
| 246 | //\r |
| 247 | // Add all the child handles as possible Console Device\r |
| 248 | //\r |
| 249 | for (Index = 0; Index < GopHandleCount; Index++) {\r |
| 250 | Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);\r |
| 251 | if (EFI_ERROR (Status)) {\r |
| 252 | continue;\r |
| 253 | }\r |
| 254 | if (CompareMem (\r |
| 255 | PciDevicePath,\r |
| 256 | TempDevicePath,\r |
| 257 | GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH\r |
| 258 | ) == 0) {\r |
| 259 | //\r |
| 260 | // In current implementation, we only enable one of the child handles\r |
| 261 | // as console device, i.e. sotre one of the child handle's device\r |
| 262 | // path to variable "ConOut"\r |
| 263 | // In futhure, we could select all child handles to be console device\r |
| 264 | //\r |
| 265 | \r |
| 266 | *GopDevicePath = TempDevicePath;\r |
| 267 | \r |
| 268 | //\r |
| 269 | // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()\r |
| 270 | // Add the integrity GOP device path.\r |
| 271 | //\r |
| 272 | BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);\r |
| 273 | BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);\r |
| 274 | }\r |
| 275 | }\r |
| 276 | gBS->FreePool (GopHandleBuffer);\r |
| 277 | }\r |
| 278 | \r |
| 279 | return EFI_SUCCESS;\r |
| 280 | }\r |
| 281 | \r |
| 282 | EFI_STATUS\r |
| 283 | PreparePciVgaDevicePath (\r |
| 284 | IN EFI_HANDLE DeviceHandle\r |
| 285 | )\r |
| 286 | /*++\r |
| 287 | \r |
| 288 | Routine Description:\r |
| 289 | \r |
| 290 | Add PCI VGA to ConOut.\r |
| 291 | PCI VGA: 03 00 00\r |
| 292 | \r |
| 293 | Arguments:\r |
| 294 | \r |
| 295 | DeviceHandle - Handle of PCIIO protocol.\r |
| 296 | \r |
| 297 | Returns:\r |
| 298 | \r |
| 299 | EFI_SUCCESS - PCI VGA is added to ConOut.\r |
| 300 | EFI_STATUS - No PCI VGA device is added.\r |
| 301 | \r |
| 302 | --*/\r |
| 303 | {\r |
| 304 | EFI_STATUS Status;\r |
| 305 | EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r |
| 306 | EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;\r |
| 307 | \r |
| 308 | DevicePath = NULL;\r |
| 309 | Status = gBS->HandleProtocol (\r |
| 310 | DeviceHandle,\r |
| 311 | &gEfiDevicePathProtocolGuid,\r |
| 312 | (VOID*)&DevicePath\r |
| 313 | );\r |
| 314 | if (EFI_ERROR (Status)) {\r |
| 315 | return Status;\r |
| 316 | }\r |
| 317 | \r |
| 318 | GetGopDevicePath (DevicePath, &GopDevicePath);\r |
| 319 | DevicePath = GopDevicePath;\r |
| 320 | \r |
| 321 | BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r |
| 322 | \r |
| 323 | return EFI_SUCCESS;\r |
| 324 | }\r |
| 325 | \r |
| 326 | EFI_STATUS\r |
| 327 | PreparePciSerialDevicePath (\r |
| 328 | IN EFI_HANDLE DeviceHandle\r |
| 329 | )\r |
| 330 | /*++\r |
| 331 | \r |
| 332 | Routine Description:\r |
| 333 | \r |
| 334 | Add PCI Serial to ConOut, ConIn, ErrOut.\r |
| 335 | PCI Serial: 07 00 02\r |
| 336 | \r |
| 337 | Arguments:\r |
| 338 | \r |
| 339 | DeviceHandle - Handle of PCIIO protocol.\r |
| 340 | \r |
| 341 | Returns:\r |
| 342 | \r |
| 343 | EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.\r |
| 344 | EFI_STATUS - No PCI Serial device is added.\r |
| 345 | \r |
| 346 | --*/\r |
| 347 | {\r |
| 348 | EFI_STATUS Status;\r |
| 349 | EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r |
| 350 | \r |
| 351 | DevicePath = NULL;\r |
| 352 | Status = gBS->HandleProtocol (\r |
| 353 | DeviceHandle,\r |
| 354 | &gEfiDevicePathProtocolGuid,\r |
| 355 | (VOID*)&DevicePath\r |
| 356 | );\r |
| 357 | if (EFI_ERROR (Status)) {\r |
| 358 | return Status;\r |
| 359 | }\r |
| 360 | \r |
| 361 | DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r |
| 362 | DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r |
| 363 | \r |
| 364 | BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r |
| 365 | BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r |
| 366 | BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r |
| 367 | \r |
| 368 | return EFI_SUCCESS;\r |
| 369 | }\r |
| 370 | \r |
| 371 | EFI_STATUS\r |
| 372 | DetectAndPreparePlatformPciDevicePath (\r |
| 373 | BOOLEAN DetectVgaOnly\r |
| 374 | )\r |
| 375 | /*++\r |
| 376 | \r |
| 377 | Routine Description:\r |
| 378 | \r |
| 379 | Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r |
| 380 | \r |
| 381 | Arguments:\r |
| 382 | \r |
| 383 | DetectVgaOnly - Only detect VGA device if it's TRUE.\r |
| 384 | \r |
| 385 | Returns:\r |
| 386 | \r |
| 387 | EFI_SUCCESS - PCI Device check and Console variable update successfully.\r |
| 388 | EFI_STATUS - PCI Device check or Console variable update fail.\r |
| 389 | \r |
| 390 | --*/\r |
| 391 | {\r |
| 392 | EFI_STATUS Status;\r |
| 393 | UINTN HandleCount;\r |
| 394 | EFI_HANDLE *HandleBuffer;\r |
| 395 | UINTN Index;\r |
| 396 | EFI_PCI_IO_PROTOCOL *PciIo;\r |
| 397 | PCI_TYPE00 Pci;\r |
| 398 | \r |
| 399 | //\r |
| 400 | // Start to check all the PciIo to find all possible device\r |
| 401 | //\r |
| 402 | HandleCount = 0;\r |
| 403 | HandleBuffer = NULL;\r |
| 404 | Status = gBS->LocateHandleBuffer (\r |
| 405 | ByProtocol,\r |
| 406 | &gEfiPciIoProtocolGuid,\r |
| 407 | NULL,\r |
| 408 | &HandleCount,\r |
| 409 | &HandleBuffer\r |
| 410 | );\r |
| 411 | if (EFI_ERROR (Status)) {\r |
| 412 | return Status;\r |
| 413 | }\r |
| 414 | \r |
| 415 | for (Index = 0; Index < HandleCount; Index++) {\r |
| 416 | Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID*)&PciIo);\r |
| 417 | if (EFI_ERROR (Status)) {\r |
| 418 | continue;\r |
| 419 | }\r |
| 420 | \r |
| 421 | //\r |
| 422 | // Check for all PCI device\r |
| 423 | //\r |
| 424 | Status = PciIo->Pci.Read (\r |
| 425 | PciIo,\r |
| 426 | EfiPciIoWidthUint32,\r |
| 427 | 0,\r |
| 428 | sizeof (Pci) / sizeof (UINT32),\r |
| 429 | &Pci\r |
| 430 | );\r |
| 431 | if (EFI_ERROR (Status)) {\r |
| 432 | continue;\r |
| 433 | }\r |
| 434 | \r |
| 435 | if (!DetectVgaOnly) {\r |
| 436 | //\r |
| 437 | // Here we decide whether it is LPC Bridge\r |
| 438 | //\r |
| 439 | if ((IS_PCI_LPC (&Pci)) ||\r |
| 440 | ((IS_PCI_ISA_PDECODE (&Pci)) &&\r |
| 441 | (Pci.Hdr.VendorId == 0x8086) &&\r |
| 442 | (Pci.Hdr.DeviceId == 0x7000)\r |
| 443 | )\r |
| 444 | ) {\r |
| 445 | Status = PciIo->Attributes (\r |
| 446 | PciIo,\r |
| 447 | EfiPciIoAttributeOperationEnable,\r |
| 448 | EFI_PCI_DEVICE_ENABLE,\r |
| 449 | NULL\r |
| 450 | );\r |
| 451 | //\r |
| 452 | // Add IsaKeyboard to ConIn,\r |
| 453 | // add IsaSerial to ConOut, ConIn, ErrOut\r |
| 454 | //\r |
| 455 | DEBUG ((EFI_D_INFO, "Find the LPC Bridge device\n"));\r |
| 456 | PrepareLpcBridgeDevicePath (HandleBuffer[Index]);\r |
| 457 | continue;\r |
| 458 | }\r |
| 459 | //\r |
| 460 | // Here we decide which Serial device to enable in PCI bus\r |
| 461 | //\r |
| 462 | if (IS_PCI_16550SERIAL (&Pci)) {\r |
| 463 | //\r |
| 464 | // Add them to ConOut, ConIn, ErrOut.\r |
| 465 | //\r |
| 466 | DEBUG ((EFI_D_INFO, "Find the 16550 SERIAL device\n"));\r |
| 467 | PreparePciSerialDevicePath (HandleBuffer[Index]);\r |
| 468 | continue;\r |
| 469 | }\r |
| 470 | }\r |
| 471 | \r |
| 472 | if ((Pci.Hdr.VendorId == 0x8086) &&\r |
| 473 | (Pci.Hdr.DeviceId == 0x7010)\r |
| 474 | ) {\r |
| 475 | Status = PciIo->Attributes (\r |
| 476 | PciIo,\r |
| 477 | EfiPciIoAttributeOperationEnable,\r |
| 478 | EFI_PCI_DEVICE_ENABLE,\r |
| 479 | NULL\r |
| 480 | );\r |
| 481 | }\r |
| 482 | \r |
| 483 | //\r |
| 484 | // Here we decide which VGA device to enable in PCI bus\r |
| 485 | //\r |
| 486 | if (IS_PCI_VGA (&Pci)) {\r |
| 487 | //\r |
| 488 | // Add them to ConOut.\r |
| 489 | //\r |
| 490 | DEBUG ((EFI_D_INFO, "Find the VGA device\n"));\r |
| 491 | PreparePciVgaDevicePath (HandleBuffer[Index]);\r |
| 492 | continue;\r |
| 493 | }\r |
| 494 | }\r |
| 495 | \r |
| 496 | gBS->FreePool (HandleBuffer);\r |
| 497 | \r |
| 498 | return EFI_SUCCESS;\r |
| 499 | }\r |
| 500 | \r |
| 501 | \r |
| 502 | EFI_STATUS\r |
| 503 | PlatformBdsConnectConsole (\r |
| 504 | IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole\r |
| 505 | )\r |
| 506 | /*++\r |
| 507 | \r |
| 508 | Routine Description:\r |
| 509 | \r |
| 510 | Connect the predefined platform default console device. Always try to find\r |
| 511 | and enable the vga device if have.\r |
| 512 | \r |
| 513 | Arguments:\r |
| 514 | \r |
| 515 | PlatformConsole - Predfined platform default console device array.\r |
| 516 | \r |
| 517 | Returns:\r |
| 518 | \r |
| 519 | EFI_SUCCESS - Success connect at least one ConIn and ConOut\r |
| 520 | device, there must have one ConOut device is\r |
| 521 | active vga device.\r |
| 522 | \r |
| 523 | EFI_STATUS - Return the status of\r |
| 524 | BdsLibConnectAllDefaultConsoles ()\r |
| 525 | \r |
| 526 | --*/\r |
| 527 | {\r |
| 528 | EFI_STATUS Status;\r |
| 529 | UINTN Index;\r |
| 530 | EFI_DEVICE_PATH_PROTOCOL *VarConout;\r |
| 531 | EFI_DEVICE_PATH_PROTOCOL *VarConin;\r |
| 532 | UINTN DevicePathSize;\r |
| 533 | \r |
| 534 | //\r |
| 535 | // Connect RootBridge\r |
| 536 | //\r |
| 537 | ConnectRootBridge ();\r |
| 538 | \r |
| 539 | VarConout = BdsLibGetVariableAndSize (\r |
| 540 | VarConsoleOut,\r |
| 541 | &gEfiGlobalVariableGuid,\r |
| 542 | &DevicePathSize\r |
| 543 | );\r |
| 544 | VarConin = BdsLibGetVariableAndSize (\r |
| 545 | VarConsoleInp,\r |
| 546 | &gEfiGlobalVariableGuid,\r |
| 547 | &DevicePathSize\r |
| 548 | );\r |
| 549 | \r |
| 550 | if (VarConout == NULL || VarConin == NULL) {\r |
| 551 | //\r |
| 552 | // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r |
| 553 | //\r |
| 554 | DetectAndPreparePlatformPciDevicePath (FALSE);\r |
| 555 | \r |
| 556 | //\r |
| 557 | // Have chance to connect the platform default console,\r |
| 558 | // the platform default console is the minimue device group\r |
| 559 | // the platform should support\r |
| 560 | //\r |
| 561 | for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {\r |
| 562 | //\r |
| 563 | // Update the console variable with the connect type\r |
| 564 | //\r |
| 565 | if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {\r |
| 566 | BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);\r |
| 567 | }\r |
| 568 | if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {\r |
| 569 | BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);\r |
| 570 | }\r |
| 571 | if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {\r |
| 572 | BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);\r |
| 573 | }\r |
| 574 | }\r |
| 575 | } else {\r |
| 576 | //\r |
| 577 | // Only detect VGA device and add them to ConOut\r |
| 578 | //\r |
| 579 | DetectAndPreparePlatformPciDevicePath (TRUE);\r |
| 580 | }\r |
| 581 | \r |
| 582 | //\r |
| 583 | // Connect the all the default console with current cosole variable\r |
| 584 | //\r |
| 585 | Status = BdsLibConnectAllDefaultConsoles ();\r |
| 586 | if (EFI_ERROR (Status)) {\r |
| 587 | return Status;\r |
| 588 | }\r |
| 589 | \r |
| 590 | return EFI_SUCCESS;\r |
| 591 | }\r |
| 592 | \r |
| 593 | \r |
| 594 | VOID\r |
| 595 | PciInitialization (\r |
| 596 | )\r |
| 597 | {\r |
| 598 | //\r |
| 599 | // Device 0 Function 0\r |
| 600 | //\r |
| 601 | PciWrite8 (PCI_LIB_ADDRESS (0,0,0,0x3c), 0x00);\r |
| 602 | \r |
| 603 | //\r |
| 604 | // Device 1 Function 0\r |
| 605 | //\r |
| 606 | PciWrite8 (PCI_LIB_ADDRESS (0,1,0,0x3c), 0x00);\r |
| 607 | PciWrite8 (PCI_LIB_ADDRESS (0,1,0,0x60), 0x8b);\r |
| 608 | PciWrite8 (PCI_LIB_ADDRESS (0,1,0,0x61), 0x89);\r |
| 609 | PciWrite8 (PCI_LIB_ADDRESS (0,1,0,0x62), 0x0a);\r |
| 610 | PciWrite8 (PCI_LIB_ADDRESS (0,1,0,0x63), 0x89);\r |
| 611 | //PciWrite8 (PCI_LIB_ADDRESS (0,1,0,0x82), 0x02);\r |
| 612 | \r |
| 613 | //\r |
| 614 | // Device 1 Function 1\r |
| 615 | //\r |
| 616 | PciWrite8 (PCI_LIB_ADDRESS (0,1,1,0x3c), 0x00);\r |
| 617 | \r |
| 618 | //\r |
| 619 | // Device 1 Function 3\r |
| 620 | //\r |
| 621 | PciWrite8 (PCI_LIB_ADDRESS (0,1,3,0x3c), 0x0b);\r |
| 622 | PciWrite8 (PCI_LIB_ADDRESS (0,1,3,0x3d), 0x01);\r |
| 623 | PciWrite8 (PCI_LIB_ADDRESS (0,1,3,0x5f), 0x90);\r |
| 624 | \r |
| 625 | //\r |
| 626 | // Device 2 Function 0\r |
| 627 | //\r |
| 628 | PciWrite8 (PCI_LIB_ADDRESS (0,2,0,0x3c), 0x00);\r |
| 629 | \r |
| 630 | //\r |
| 631 | // Device 3 Function 0\r |
| 632 | //\r |
| 633 | PciWrite8 (PCI_LIB_ADDRESS (0,3,0,0x3c), 0x0b);\r |
| 634 | PciWrite8 (PCI_LIB_ADDRESS (0,3,0,0x3d), 0x01);\r |
| 635 | }\r |
| 636 | \r |
| 637 | \r |
| 638 | VOID\r |
| 639 | PlatformBdsConnectSequence (\r |
| 640 | VOID\r |
| 641 | )\r |
| 642 | /*++\r |
| 643 | \r |
| 644 | Routine Description:\r |
| 645 | \r |
| 646 | Connect with predeined platform connect sequence,\r |
| 647 | the OEM/IBV can customize with their own connect sequence.\r |
| 648 | \r |
| 649 | Arguments:\r |
| 650 | \r |
| 651 | None.\r |
| 652 | \r |
| 653 | Returns:\r |
| 654 | \r |
| 655 | None.\r |
| 656 | \r |
| 657 | --*/\r |
| 658 | {\r |
| 659 | UINTN Index;\r |
| 660 | \r |
| 661 | DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));\r |
| 662 | \r |
| 663 | Index = 0;\r |
| 664 | \r |
| 665 | //\r |
| 666 | // Here we can get the customized platform connect sequence\r |
| 667 | // Notes: we can connect with new variable which record the\r |
| 668 | // last time boots connect device path sequence\r |
| 669 | //\r |
| 670 | while (gPlatformConnectSequence[Index] != NULL) {\r |
| 671 | //\r |
| 672 | // Build the platform boot option\r |
| 673 | //\r |
| 674 | BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);\r |
| 675 | Index++;\r |
| 676 | }\r |
| 677 | \r |
| 678 | //\r |
| 679 | // Just use the simple policy to connect all devices\r |
| 680 | //\r |
| 681 | BdsLibConnectAll ();\r |
| 682 | \r |
| 683 | PciInitialization ();\r |
| 684 | }\r |
| 685 | \r |
| 686 | VOID\r |
| 687 | PlatformBdsGetDriverOption (\r |
| 688 | IN OUT LIST_ENTRY *BdsDriverLists\r |
| 689 | )\r |
| 690 | /*++\r |
| 691 | \r |
| 692 | Routine Description:\r |
| 693 | \r |
| 694 | Load the predefined driver option, OEM/IBV can customize this\r |
| 695 | to load their own drivers\r |
| 696 | \r |
| 697 | Arguments:\r |
| 698 | \r |
| 699 | BdsDriverLists - The header of the driver option link list.\r |
| 700 | \r |
| 701 | Returns:\r |
| 702 | \r |
| 703 | None.\r |
| 704 | \r |
| 705 | --*/\r |
| 706 | {\r |
| 707 | DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));\r |
| 708 | return;\r |
| 709 | }\r |
| 710 | \r |
| 711 | VOID\r |
| 712 | PlatformBdsDiagnostics (\r |
| 713 | IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,\r |
| 714 | IN BOOLEAN QuietBoot\r |
| 715 | )\r |
| 716 | /*++\r |
| 717 | \r |
| 718 | Routine Description:\r |
| 719 | \r |
| 720 | Perform the platform diagnostic, such like test memory. OEM/IBV also\r |
| 721 | can customize this fuction to support specific platform diagnostic.\r |
| 722 | \r |
| 723 | Arguments:\r |
| 724 | \r |
| 725 | MemoryTestLevel - The memory test intensive level\r |
| 726 | \r |
| 727 | QuietBoot - Indicate if need to enable the quiet boot\r |
| 728 | \r |
| 729 | Returns:\r |
| 730 | \r |
| 731 | None.\r |
| 732 | \r |
| 733 | --*/\r |
| 734 | {\r |
| 735 | EFI_STATUS Status;\r |
| 736 | \r |
| 737 | DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));\r |
| 738 | \r |
| 739 | //\r |
| 740 | // Here we can decide if we need to show\r |
| 741 | // the diagnostics screen\r |
| 742 | // Notes: this quiet boot code should be remove\r |
| 743 | // from the graphic lib\r |
| 744 | //\r |
| 745 | if (QuietBoot) {\r |
| 746 | EnableQuietBoot (&gEfiDefaultBmpLogoGuid);\r |
| 747 | //\r |
| 748 | // Perform system diagnostic\r |
| 749 | //\r |
| 750 | Status = BdsMemoryTest (MemoryTestLevel);\r |
| 751 | if (EFI_ERROR (Status)) {\r |
| 752 | DisableQuietBoot ();\r |
| 753 | }\r |
| 754 | \r |
| 755 | return ;\r |
| 756 | }\r |
| 757 | //\r |
| 758 | // Perform system diagnostic\r |
| 759 | //\r |
| 760 | Status = BdsMemoryTest (MemoryTestLevel);\r |
| 761 | }\r |
| 762 | \r |
| 763 | \r |
| 764 | VOID\r |
| 765 | EFIAPI\r |
| 766 | PlatformBdsPolicyBehavior (\r |
| 767 | IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData,\r |
| 768 | IN OUT LIST_ENTRY *DriverOptionList,\r |
| 769 | IN OUT LIST_ENTRY *BootOptionList\r |
| 770 | )\r |
| 771 | /*++\r |
| 772 | \r |
| 773 | Routine Description:\r |
| 774 | \r |
| 775 | The function will excute with as the platform policy, current policy\r |
| 776 | is driven by boot mode. IBV/OEM can customize this code for their specific\r |
| 777 | policy action.\r |
| 778 | \r |
| 779 | Arguments:\r |
| 780 | \r |
| 781 | PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance\r |
| 782 | \r |
| 783 | DriverOptionList - The header of the driver option link list\r |
| 784 | \r |
| 785 | BootOptionList - The header of the boot option link list\r |
| 786 | \r |
| 787 | Returns:\r |
| 788 | \r |
| 789 | None.\r |
| 790 | \r |
| 791 | --*/\r |
| 792 | {\r |
| 793 | EFI_STATUS Status;\r |
| 794 | UINT16 Timeout;\r |
| 795 | EFI_EVENT UserInputDurationTime;\r |
| 796 | LIST_ENTRY *Link;\r |
| 797 | BDS_COMMON_OPTION *BootOption;\r |
| 798 | UINTN Index;\r |
| 799 | EFI_INPUT_KEY Key;\r |
| 800 | EFI_TPL OldTpl;\r |
| 801 | \r |
| 802 | DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));\r |
| 803 | \r |
| 804 | //\r |
| 805 | // Init the time out value\r |
| 806 | //\r |
| 807 | Timeout = PcdGet16 (PcdPlatformBootTimeOut);\r |
| 808 | \r |
| 809 | //\r |
| 810 | // Load the driver option as the driver option list\r |
| 811 | //\r |
| 812 | PlatformBdsGetDriverOption (DriverOptionList);\r |
| 813 | \r |
| 814 | //\r |
| 815 | // Get current Boot Mode\r |
| 816 | //\r |
| 817 | Status = BdsLibGetBootMode (&PrivateData->BootMode);\r |
| 818 | DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", PrivateData->BootMode));\r |
| 819 | \r |
| 820 | //\r |
| 821 | // Go the different platform policy with different boot mode\r |
| 822 | // Notes: this part code can be change with the table policy\r |
| 823 | //\r |
| 824 | ASSERT (PrivateData->BootMode == BOOT_WITH_FULL_CONFIGURATION);\r |
| 825 | //\r |
| 826 | // Connect platform console\r |
| 827 | //\r |
| 828 | Status = PlatformBdsConnectConsole (gPlatformConsole);\r |
| 829 | if (EFI_ERROR (Status)) {\r |
| 830 | //\r |
| 831 | // Here OEM/IBV can customize with defined action\r |
| 832 | //\r |
| 833 | PlatformBdsNoConsoleAction ();\r |
| 834 | }\r |
| 835 | //\r |
| 836 | // Create a 300ms duration event to ensure user has enough input time to enter Setup\r |
| 837 | //\r |
| 838 | Status = gBS->CreateEvent (\r |
| 839 | EVT_TIMER,\r |
| 840 | 0,\r |
| 841 | NULL,\r |
| 842 | NULL,\r |
| 843 | &UserInputDurationTime\r |
| 844 | );\r |
| 845 | ASSERT (Status == EFI_SUCCESS);\r |
| 846 | Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);\r |
| 847 | ASSERT (Status == EFI_SUCCESS);\r |
| 848 | //\r |
| 849 | // Memory test and Logo show\r |
| 850 | //\r |
| 851 | PlatformBdsDiagnostics (IGNORE, TRUE);\r |
| 852 | \r |
| 853 | //\r |
| 854 | // Perform some platform specific connect sequence\r |
| 855 | //\r |
| 856 | PlatformBdsConnectSequence ();\r |
| 857 | \r |
| 858 | //\r |
| 859 | // Give one chance to enter the setup if we\r |
| 860 | // have the time out\r |
| 861 | //\r |
| 862 | if (Timeout != 0) {\r |
| 863 | //PlatformBdsEnterFrontPage (Timeout, FALSE);\r |
| 864 | }\r |
| 865 | \r |
| 866 | DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));\r |
| 867 | BdsLibConnectAll ();\r |
| 868 | BdsLibEnumerateAllBootOption (BootOptionList);\r |
| 869 | \r |
| 870 | //\r |
| 871 | // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot\r |
| 872 | // checking code in real production tip.\r |
| 873 | //\r |
| 874 | // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device\r |
| 875 | // and do enumerate all the default boot options. But in development system board, the boot mode\r |
| 876 | // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box\r |
| 877 | // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.\r |
| 878 | //\r |
| 879 | Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");\r |
| 880 | if (EFI_ERROR(Status)) {\r |
| 881 | //\r |
| 882 | // If cannot find "BootOrder" variable, it may be first boot.\r |
| 883 | // Try to connect all devices and enumerate all boot options here.\r |
| 884 | //\r |
| 885 | BdsLibConnectAll ();\r |
| 886 | BdsLibEnumerateAllBootOption (BootOptionList);\r |
| 887 | }\r |
| 888 | \r |
| 889 | //\r |
| 890 | // To give the User a chance to enter Setup here, if user set TimeOut is 0.\r |
| 891 | // BDS should still give user a chance to enter Setup\r |
| 892 | //\r |
| 893 | // Connect first boot option, and then check user input before exit\r |
| 894 | //\r |
| 895 | for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {\r |
| 896 | BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r |
| 897 | if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {\r |
| 898 | //\r |
| 899 | // skip the header of the link list, becuase it has no boot option\r |
| 900 | //\r |
| 901 | continue;\r |
| 902 | } else {\r |
| 903 | //\r |
| 904 | // Make sure the boot option device path connected, but ignore the BBS device path\r |
| 905 | //\r |
| 906 | if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {\r |
| 907 | BdsLibConnectDevicePath (BootOption->DevicePath);\r |
| 908 | }\r |
| 909 | break;\r |
| 910 | }\r |
| 911 | }\r |
| 912 | \r |
| 913 | //\r |
| 914 | // Check whether the user input after the duration time has expired\r |
| 915 | //\r |
| 916 | OldTpl = EfiGetCurrentTpl();\r |
| 917 | gBS->RestoreTPL (TPL_APPLICATION);\r |
| 918 | gBS->WaitForEvent (1, &UserInputDurationTime, &Index);\r |
| 919 | gBS->CloseEvent (UserInputDurationTime);\r |
| 920 | Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r |
| 921 | gBS->RaiseTPL (OldTpl);\r |
| 922 | \r |
| 923 | if (!EFI_ERROR (Status)) {\r |
| 924 | //\r |
| 925 | // Enter Setup if user input\r |
| 926 | //\r |
| 927 | Timeout = 0xffff;\r |
| 928 | PlatformBdsEnterFrontPage (Timeout, FALSE);\r |
| 929 | }\r |
| 930 | \r |
| 931 | return ;\r |
| 932 | }\r |
| 933 | \r |
| 934 | VOID\r |
| 935 | EFIAPI\r |
| 936 | PlatformBdsBootSuccess (\r |
| 937 | IN BDS_COMMON_OPTION *Option\r |
| 938 | )\r |
| 939 | /*++\r |
| 940 | \r |
| 941 | Routine Description:\r |
| 942 | \r |
| 943 | Hook point after a boot attempt succeeds. We don't expect a boot option to\r |
| 944 | return, so the EFI 1.0 specification defines that you will default to an\r |
| 945 | interactive mode and stop processing the BootOrder list in this case. This\r |
| 946 | is alos a platform implementation and can be customized by IBV/OEM.\r |
| 947 | \r |
| 948 | Arguments:\r |
| 949 | \r |
| 950 | Option - Pointer to Boot Option that succeeded to boot.\r |
| 951 | \r |
| 952 | Returns:\r |
| 953 | \r |
| 954 | None.\r |
| 955 | \r |
| 956 | --*/\r |
| 957 | {\r |
| 958 | CHAR16 *TmpStr;\r |
| 959 | \r |
| 960 | DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));\r |
| 961 | //\r |
| 962 | // If Boot returned with EFI_SUCCESS and there is not in the boot device\r |
| 963 | // select loop then we need to pop up a UI and wait for user input.\r |
| 964 | //\r |
| 965 | TmpStr = Option->StatusString;\r |
| 966 | if (TmpStr != NULL) {\r |
| 967 | BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r |
| 968 | FreePool (TmpStr);\r |
| 969 | }\r |
| 970 | }\r |
| 971 | \r |
| 972 | VOID\r |
| 973 | EFIAPI\r |
| 974 | PlatformBdsBootFail (\r |
| 975 | IN BDS_COMMON_OPTION *Option,\r |
| 976 | IN EFI_STATUS Status,\r |
| 977 | IN CHAR16 *ExitData,\r |
| 978 | IN UINTN ExitDataSize\r |
| 979 | )\r |
| 980 | /*++\r |
| 981 | \r |
| 982 | Routine Description:\r |
| 983 | \r |
| 984 | Hook point after a boot attempt fails.\r |
| 985 | \r |
| 986 | Arguments:\r |
| 987 | \r |
| 988 | Option - Pointer to Boot Option that failed to boot.\r |
| 989 | \r |
| 990 | Status - Status returned from failed boot.\r |
| 991 | \r |
| 992 | ExitData - Exit data returned from failed boot.\r |
| 993 | \r |
| 994 | ExitDataSize - Exit data size returned from failed boot.\r |
| 995 | \r |
| 996 | Returns:\r |
| 997 | \r |
| 998 | None.\r |
| 999 | \r |
| 1000 | --*/\r |
| 1001 | {\r |
| 1002 | CHAR16 *TmpStr;\r |
| 1003 | \r |
| 1004 | DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));\r |
| 1005 | \r |
| 1006 | //\r |
| 1007 | // If Boot returned with failed status then we need to pop up a UI and wait\r |
| 1008 | // for user input.\r |
| 1009 | //\r |
| 1010 | TmpStr = Option->StatusString;\r |
| 1011 | if (TmpStr != NULL) {\r |
| 1012 | BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r |
| 1013 | FreePool (TmpStr);\r |
| 1014 | }\r |
| 1015 | }\r |
| 1016 | \r |
| 1017 | EFI_STATUS\r |
| 1018 | PlatformBdsNoConsoleAction (\r |
| 1019 | VOID\r |
| 1020 | )\r |
| 1021 | /*++\r |
| 1022 | \r |
| 1023 | Routine Description:\r |
| 1024 | \r |
| 1025 | This function is remained for IBV/OEM to do some platform action,\r |
| 1026 | if there no console device can be connected.\r |
| 1027 | \r |
| 1028 | Arguments:\r |
| 1029 | \r |
| 1030 | None.\r |
| 1031 | \r |
| 1032 | Returns:\r |
| 1033 | \r |
| 1034 | EFI_SUCCESS - Direct return success now.\r |
| 1035 | \r |
| 1036 | --*/\r |
| 1037 | {\r |
| 1038 | DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));\r |
| 1039 | return EFI_SUCCESS;\r |
| 1040 | }\r |
| 1041 | \r |
| 1042 | EFI_STATUS\r |
| 1043 | EFIAPI\r |
| 1044 | PlatformBdsLockNonUpdatableFlash (\r |
| 1045 | VOID\r |
| 1046 | )\r |
| 1047 | {\r |
| 1048 | DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));\r |
| 1049 | return EFI_SUCCESS;\r |
| 1050 | }\r |