winntbusdriver.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 865 行 · 第 1/2 页

C
865
字号

    //
    // We found the EFI_WIN_NT_PASS_THROUGH variable defined
    //
    if (EfiCompareGuid (mEnvironment[Index].DevicePathGuid, &gEfiWinNtPassThroughGuid) && (Result > 0)) {
      if (!gHostBridgeInit) {
        StartString = (CHAR16 *) NtEnvironmentVariableBuffer;
        Count       = 0;

        while (*StartString != '\0') {
          //
          // Is it a numeric value?
          //
          if (*StartString >= L'0' && *StartString <= L'9') {
            Value = *StartString - L'0';
          } else if (*StartString >= L'a' && *StartString <= L'f') {
            Value = *StartString - L'a' + 10;
          } else if (*StartString >= L'A' && *StartString <= L'F') {
            Value = *StartString - L'A' + 10;
          } else if (*StartString == L';') {
            StartString++;
            Count++;
            continue;
          } else {
            StartString++;
            continue;
          }

          switch (Count) {
          case 0:
            gBaseAddress = gBaseAddress * 16 + Value;
            break;

          case 1:
            gConfigData.Bus = gConfigData.Bus * 16 + Value;
            break;

          case 2:
            gConfigData.Dev = gConfigData.Dev * 16 + Value;
            break;

          case 3:
            gConfigData.Func = gConfigData.Func * 16 + Value;
            break;
          }

          StartString++;
        }

        continue;
      }
    }

    if (Result == 0) {
      if ((EfiCompareGuid (mEnvironment[Index].DevicePathGuid, &gEfiWinNtUgaGuid) && NoWinNtConsole) ||
          (EfiCompareGuid (mEnvironment[Index].DevicePathGuid, &gEfiWinNtGopGuid) && NoWinNtConsole)) {
        //
        // If there is no GOP or UGA force a default 800 x 600 console
        //
        StartString = L"800 600";
      } else {
        if (EfiCompareGuid (mEnvironment[Index].DevicePathGuid, &gEfiWinNtConsoleGuid)) {
          NoWinNtConsole = TRUE;
        }

        continue;
      }
    } else {
      StartString = (CHAR16 *) NtEnvironmentVariableBuffer;
    }

    //
    // Parse the envirnment variable into sub strings using '!' as a delimator.
    // Each substring needs it's own handle to be added to the system. This code
    // does not understand the sub string. Thats the device drivers job.
    //
    Count = 0;
    while (*StartString != '\0') {

      //
      // Find the end of the sub string
      //
      SubString = StartString;
      while (*SubString != '\0' && *SubString != '!') {
        SubString++;
      }

      if (*SubString == '!') {
        //
        // Replace token with '\0' to make sub strings. If this is the end
        //  of the string SubString will already point to NULL.
        //
        *SubString = '\0';
        SubString++;
      }

      CreateDevice = TRUE;
      if (RemainingDevicePath != NULL) {
        CreateDevice  = FALSE;
        Node          = (WIN_NT_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath;
        if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH &&
            Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP &&
            DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)
            ) {
          if (EfiCompareGuid (&Node->VendorDevicePath.Guid, mEnvironment[Index].DevicePathGuid) &&
              Node->Instance == Count
              ) {
            CreateDevice = TRUE;
          }
        }
      }

      if (CreateDevice) {

        //
        // Allocate instance structure, and fill in parent information.
        //
        Status = gBS->AllocatePool (
                        EfiBootServicesData,
                        sizeof (WIN_NT_IO_DEVICE),
                        (VOID *) &WinNtDevice
                        );
        if (EFI_ERROR (Status)) {
          return EFI_OUT_OF_RESOURCES;
        }

        WinNtDevice->Handle             = NULL;
        WinNtDevice->ControllerHandle   = ControllerHandle;
        WinNtDevice->ParentDevicePath   = ParentDevicePath;

        WinNtDevice->WinNtIo.WinNtThunk = WinNtThunk;

        //
        // Plus 2 to account for the NULL at the end of the Unicode string
        //
        StringSize = (UINTN) ((UINT8 *) SubString - (UINT8 *) StartString) + 2;
        Status = gBS->AllocatePool (
                        EfiBootServicesData,
                        StringSize,
                        (VOID *) &WinNtDevice->WinNtIo.EnvString
                        );
        if (EFI_ERROR (Status)) {
          WinNtDevice->WinNtIo.EnvString = NULL;
        } else {
          EfiCopyMem (WinNtDevice->WinNtIo.EnvString, StartString, StringSize);
        }

        WinNtDevice->ControllerNameTable = NULL;

        WinNtThunk->SPrintf (ComponentName, L"%s=%s", mEnvironment[Index].Variable, WinNtDevice->WinNtIo.EnvString);

        WinNtDevice->DevicePath = WinNtBusCreateDevicePath (
                                    ParentDevicePath,
                                    mEnvironment[Index].DevicePathGuid,
                                    Count
                                    );
        if (WinNtDevice->DevicePath == NULL) {
          gBS->FreePool (WinNtDevice);
          return EFI_OUT_OF_RESOURCES;
        }

        EfiLibAddUnicodeString (
          "eng",
          gWinNtBusDriverComponentName.SupportedLanguages,
          &WinNtDevice->ControllerNameTable,
          ComponentName
          );

        WinNtDevice->WinNtIo.TypeGuid       = mEnvironment[Index].DevicePathGuid;
        WinNtDevice->WinNtIo.InstanceNumber = Count;

        WinNtDevice->Signature              = WIN_NT_IO_DEVICE_SIGNATURE;

        Status = gBS->InstallMultipleProtocolInterfaces (
                        &WinNtDevice->Handle,
                        &gEfiDevicePathProtocolGuid,
                        WinNtDevice->DevicePath,
                        &gEfiWinNtIoProtocolGuid,
                        &WinNtDevice->WinNtIo,
                        NULL
                        );
        if (EFI_ERROR (Status)) {
          EfiLibFreeUnicodeStringTable (WinNtDevice->ControllerNameTable);
          gBS->FreePool (WinNtDevice);
        } else {
          //
          // Open For Child Device
          //
          Status = gBS->OpenProtocol (
                          ControllerHandle,
                          &gEfiWinNtThunkProtocolGuid,
                          &WinNtThunk,
                          This->DriverBindingHandle,
                          WinNtDevice->Handle,
                          EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
                          );
          if (!EFI_ERROR (Status)) {
            InstallStatus = EFI_SUCCESS;
          }
        }
      }

      //
      // Parse Next sub string. This will point to '\0' if we are at the end.
      //
      Count++;
      StartString = SubString;
    }
  }

  gDeviceHandle = WinNtThunk->CreateFile (
                                L"\\\\.\\DeviceUnderDevelopment", // Open the Kernel driver "file"/IOCTL
                                GENERIC_READ,                     // Open the interface Read-Only
                                FILE_SHARE_READ,                  // Allow others to get Read-Only access
                                NULL,                             // Default security options
                                OPEN_EXISTING,                    // Succeeds only if Kernel driver exported interface
                                0,                                // Not used for non-file objects
                                NULL                              // No template since not opening a real file
                                );

  //
  // Did we successfully open the IOCTL?
  //
  if (gDeviceHandle != INVALID_HANDLE_VALUE) {
    //
    // Call out to HostBridge Constructor - do it once, and never again
    // Pass in the parameters we discovered in the variable.
    // We do this only if the expected Kernel driver installed an interface for us
    //
    if (!gHostBridgeInit) {
      InitializePciHostBridge (gImageHandle, gST);
      gHostBridgeInit = TRUE;
    }
  }

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
WinNtBusDriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN  EFI_HANDLE                   ControllerHandle,
  IN  UINTN                        NumberOfChildren,
  IN  EFI_HANDLE                   *ChildHandleBuffer
  )
/*++

Routine Description:

Arguments:

Returns:

    None

--*/
// TODO:    This - add argument and description to function comment
// TODO:    ControllerHandle - add argument and description to function comment
// TODO:    NumberOfChildren - add argument and description to function comment
// TODO:    ChildHandleBuffer - add argument and description to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
// TODO:    EFI_DEVICE_ERROR - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
{
  EFI_STATUS                Status;
  UINTN                     Index;
  BOOLEAN                   AllChildrenStopped;
  EFI_WIN_NT_IO_PROTOCOL    *WinNtIo;
  WIN_NT_BUS_DEVICE         *WinNtBusDevice;
  WIN_NT_IO_DEVICE          *WinNtDevice;
  EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk;

  //
  // Complete all outstanding transactions to Controller.
  // Don't allow any new transaction to Controller to be started.
  //

  if (NumberOfChildren == 0) {
    //
    // Close the bus driver
    //
    Status = gBS->OpenProtocol (
                    ControllerHandle,
                    &gWinNtBusDriverGuid,
                    &WinNtBusDevice,
                    This->DriverBindingHandle,
                    ControllerHandle,
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    gBS->UninstallMultipleProtocolInterfaces (
          ControllerHandle,
          &gWinNtBusDriverGuid,
          WinNtBusDevice,
          NULL
          );

    EfiLibFreeUnicodeStringTable (WinNtBusDevice->ControllerNameTable);

    gBS->FreePool (WinNtBusDevice);

    gBS->CloseProtocol (
          ControllerHandle,
          &gEfiWinNtThunkProtocolGuid,
          This->DriverBindingHandle,
          ControllerHandle
          );

    gBS->CloseProtocol (
          ControllerHandle,
          &gEfiDevicePathProtocolGuid,
          This->DriverBindingHandle,
          ControllerHandle
          );
    return EFI_SUCCESS;
  }

  AllChildrenStopped = TRUE;

  for (Index = 0; Index < NumberOfChildren; Index++) {

    Status = gBS->OpenProtocol (
                    ChildHandleBuffer[Index],
                    &gEfiWinNtIoProtocolGuid,
                    &WinNtIo,
                    This->DriverBindingHandle,
                    ControllerHandle,
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
                    );
    if (!EFI_ERROR (Status)) {

      WinNtDevice = WIN_NT_IO_DEVICE_FROM_THIS (WinNtIo);

      Status = gBS->CloseProtocol (
                      ControllerHandle,
                      &gEfiWinNtThunkProtocolGuid,
                      This->DriverBindingHandle,
                      WinNtDevice->Handle
                      );

      Status = gBS->UninstallMultipleProtocolInterfaces (
                      WinNtDevice->Handle,
                      &gEfiDevicePathProtocolGuid,
                      WinNtDevice->DevicePath,
                      &gEfiWinNtIoProtocolGuid,
                      &WinNtDevice->WinNtIo,
                      NULL
                      );

      if (EFI_ERROR (Status)) {
        gBS->OpenProtocol (
              ControllerHandle,
              &gEfiWinNtThunkProtocolGuid,
              (VOID **) &WinNtThunk,
              This->DriverBindingHandle,
              WinNtDevice->Handle,
              EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
              );
      } else {
        //
        // Close the child handle
        //
        EfiLibFreeUnicodeStringTable (WinNtDevice->ControllerNameTable);
        gBS->FreePool (WinNtDevice);
      }
    }

    if (EFI_ERROR (Status)) {
      AllChildrenStopped = FALSE;
    }
  }

  if (!AllChildrenStopped) {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

EFI_DEVICE_PATH_PROTOCOL *
WinNtBusCreateDevicePath (
  IN  EFI_DEVICE_PATH_PROTOCOL  *RootDevicePath,
  IN  EFI_GUID                  *Guid,
  IN  UINT16                    InstanceNumber
  )
/*++

Routine Description:
  Create a device path node using Guid and InstanceNumber and append it to
  the passed in RootDevicePath

Arguments:
  RootDevicePath - Root of the device path to return.

  Guid           - GUID to use in vendor device path node.

  InstanceNumber - Instance number to use in the vendor device path. This
                    argument is needed to make sure each device path is unique.

Returns:

  EFI_DEVICE_PATH_PROTOCOL 

--*/
{
  WIN_NT_VENDOR_DEVICE_PATH_NODE  DevicePath;

  DevicePath.VendorDevicePath.Header.Type     = HARDWARE_DEVICE_PATH;
  DevicePath.VendorDevicePath.Header.SubType  = HW_VENDOR_DP;
  SetDevicePathNodeLength (&DevicePath.VendorDevicePath.Header, sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE));

  //
  // The GUID defines the Class
  //
  EfiCopyMem (&DevicePath.VendorDevicePath.Guid, Guid, sizeof (EFI_GUID));

  //
  // Add an instance number so we can make sure there are no Device Path
  // duplication.
  //
  DevicePath.Instance = InstanceNumber;

  return EfiAppendDevicePathNode (
          RootDevicePath,
          (EFI_DEVICE_PATH_PROTOCOL *) &DevicePath
          );
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?