winntbusdriver.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 688 行 · 第 1/2 页

C
688
字号
  NoWinNtConsole = FALSE;
  InstallStatus = EFI_NOT_FOUND;
  for (Index = 0; mEnvironment[Index].Variable != NULL ; Index++) {
    Result = WinNtThunk->GetEnvironmentVariable (
                           mEnvironment[Index].Variable,
                           (CHAR16 *)NtEnvironmentVariableBuffer, MAX_NT_ENVIRNMENT_VARIABLE_LENGTH
                           );
    if (Result == 0) {
      if (EfiCompareGuid (mEnvironment[Index].DevicePathGuid, &gEfiWinNtUgaGuid) && NoWinNtConsole) {
        //
        // If there is no 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 == TRUE) {

        //
        // 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;
    }
  }

  return EFI_SUCCESS;
}

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

Routine Description:

Arguments:

Returns:

    None

--*/
{
  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 + -
显示快捷键?