conplatform.c

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

C
948
字号
    //
    // Get the Device Path Protocol so the environment variables can be updated
    //
    Status = gBS->OpenProtocol (
                    ControllerHandle, 
                    &gEfiDevicePathProtocolGuid, 
                    (VOID **)&DevicePath,
                    This->DriverBindingHandle,
                    ControllerHandle, 
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
                    );
    if (!EFI_ERROR (Status)) {
      //
      // Remove DevicePath from ConInDev, ConOutDev, and StdErrDev
      //
      Status = ConPlatformUpdateDeviceVariable (
                                  VarConsoleInpDev,
                                  DevicePath,
                                  FALSE
                                  );
      Status = ConPlatformUpdateDeviceVariable (
                                  VarConsoleOutDev,
                                  DevicePath,
                                  FALSE
                                  );
      Status = ConPlatformUpdateDeviceVariable (
                                  VarErrorOutDev,
                                  DevicePath,
                                  FALSE
                                  );
    }
  }
  
  //
  // Uninstall the Console Device GUIDs from Controller Handle
  //
  Status = gBS->OpenProtocol (
                ControllerHandle, 
                &gEfiConsoleInDeviceGuid, 
                NULL,
                This->DriverBindingHandle,
                ControllerHandle, 
                EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                );
  if (!EFI_ERROR (Status)) {
    Status = gBS->UninstallMultipleProtocolInterfaces (
                    ControllerHandle,
                    &gEfiConsoleInDeviceGuid, NULL,
                    NULL
                    );
  }

  Status = gBS->OpenProtocol (
                ControllerHandle, 
                &gEfiConsoleOutDeviceGuid, 
                NULL,
                This->DriverBindingHandle,
                ControllerHandle, 
                EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                );
  if (!EFI_ERROR (Status)) {
    Status = gBS->UninstallMultipleProtocolInterfaces (
                    ControllerHandle,
                    &gEfiConsoleOutDeviceGuid, NULL,
                    NULL
                    );
  }

  Status = gBS->OpenProtocol (
                ControllerHandle, 
                &gEfiStandardErrorDeviceGuid, 
                NULL,
                This->DriverBindingHandle,
                ControllerHandle, 
                EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                );
  if (!EFI_ERROR (Status)) {
    Status = gBS->UninstallMultipleProtocolInterfaces (
                    ControllerHandle,
                    &gEfiStandardErrorDeviceGuid, NULL,
                    NULL
                    );
  }

  //
  // Close the Simple Input and Simple Text Output Protocols
  //
  Status = gBS->CloseProtocol (
                  ControllerHandle, 
                  &gEfiSimpleTextInProtocolGuid, 
                  This->DriverBindingHandle,
                  ControllerHandle 
                  );

  Status = gBS->CloseProtocol (
                  ControllerHandle, 
                  &gEfiSimpleTextOutProtocolGuid, 
                  This->DriverBindingHandle,
                  ControllerHandle 
                  );

  return EFI_SUCCESS;
}

VOID *
ConPlatformGetVariableAndSize (
  IN  CHAR16    *Name,
  IN  EFI_GUID  *VendorGuid,
  OUT UINTN     *VariableSize
  )
/*++

Routine Description:
  Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
  buffer, and the size of the buffer. On failure return NULL.

Arguments:
  Name       - String part of EFI variable name

  VendorGuid - GUID part of EFI variable name

  VariableSize - Returns the size of the EFI variable that was read

Returns:
  Dynamically allocated memory that contains a copy of the EFI variable.
  Caller is repsoncible freeing the buffer.

  NULL - Variable was not read
  
--*/
{
  EFI_STATUS  Status;
  VOID        *Buffer;

  //
  // Allocate a small buffer to test if the variable exists.
  //
  *VariableSize = 1;
  Status = gBS->AllocatePool (EfiBootServicesData, *VariableSize, &Buffer); 
  if (EFI_ERROR (Status)) {
    *VariableSize = 0;
    return NULL;
  }
  
  //
  // Test to see if the variable exists.  If it doesn't then free Buffer
  // and return NULL.
  //
  Status = gRT->GetVariable (Name, VendorGuid, NULL, VariableSize, Buffer);
  
  if (Status == EFI_SUCCESS) {
    return Buffer;
  
  } else if (Status == EFI_BUFFER_TOO_SMALL) {
    //
    // Allocate the buffer to return
    //
    gBS->FreePool (Buffer);
    Status = gBS->AllocatePool (EfiBootServicesData, *VariableSize, &Buffer); 
    if (EFI_ERROR (Status)) {
      *VariableSize = 0;
      return NULL;
    }

    //
    // Read variable into the allocated buffer.
    //
    Status = gRT->GetVariable (Name, VendorGuid, NULL, VariableSize, Buffer);
    if (EFI_ERROR (Status)) {
      *VariableSize = 0;
      gBS->FreePool (Buffer);
      return NULL;
    }
    
    return Buffer;
    
  } else {
    //
    // Variable not found or other errors met.
    //
    *VariableSize = 0;
    gBS->FreePool (Buffer);
    return NULL;
  }
}

EFI_STATUS
ConPlatformMatchDevicePaths (
  IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,
  IN  EFI_DEVICE_PATH_PROTOCOL  *Single,
  IN  EFI_DEVICE_PATH_PROTOCOL  **NewDevicePath  OPTIONAL,
  IN  BOOLEAN                   Delete
  )
/*++

Routine Description:
  Function compares a device path data structure to that of all the nodes of a
  second device path instance.

Arguments:
  Multi        - A pointer to a multi-instance device path data structure.

  Single       - A pointer to a single-instance device path data structure.
  
  NewDevicePath - If Delete is TRUE, this parameter must not be null, and it
                  points to the remaining device path data structure. 
                  (remaining device path = Multi - Single.)
  
  Delete        - If TRUE, means removing Single from Multi.
                  If FALSE, the routine just check whether Single matches 
                  with any instance in Multi.

Returns:

  The function returns EFI_SUCCESS if the Single is contained within Multi.  
  Otherwise, EFI_NOT_FOUND is returned.

--*/
{
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;
  UINTN                     Size;
  
  //
  // if performing Delete operation, the NewDevicePath must not be NULL.
  //
  if (Delete) {
    if (NewDevicePath == NULL) {
      return EFI_INVALID_PARAMETER;
    }
    *NewDevicePath = NULL;
  }
  
  if (!Multi || !Single) {
    return EFI_NOT_FOUND;
  }

  DevicePath = Multi;
  DevicePathInst = EfiDevicePathInstance (&DevicePath, &Size);
  //
  // search for the match of 'Single' in 'Multi'
  //
  while (DevicePathInst != NULL) {
    if (EfiCompareMem (Single, DevicePathInst, Size) == 0) {
      if (!Delete) {
        return EFI_SUCCESS;
      }
    } else {
      if (Delete) {
        TempDevicePath = EfiAppendDevicePathInstance (*NewDevicePath, 
                                                      DevicePathInst);          
        if (*NewDevicePath) {
          gBS->FreePool (*NewDevicePath);
        }
        *NewDevicePath = TempDevicePath;
      }
    }
    gBS->FreePool(DevicePathInst);
    DevicePathInst = EfiDevicePathInstance (&DevicePath, &Size);
  }

  if (Delete) {
    return EFI_SUCCESS;
  }

  return EFI_NOT_FOUND;
}

EFI_STATUS
ConPlatformCheckVariable (
  IN  CHAR16                    *VariableName,
  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath
  )
/*++

Routine Description:
  

Arguments:

Returns:

  None

--*/  
{
  UINT8                     *Variable;
  UINTN                     VariableSize;
  EFI_DEVICE_PATH_PROTOCOL  *VariableDevicePath;
  EFI_STATUS                Status;
  
  Variable = NULL;
  
  //
  // Get Variable and its size according to variable name.
  // The memory for Variable is allocated within ConPlatformGetVaribleAndSize(),
  // it is the caller's responsibility to free the memory before return. 
  //
  Variable = ConPlatformGetVariableAndSize (
               VariableName,
               &gEfiGlobalVariableGuid,
               &VariableSize  
               );
  //
  // The Variable was not found
  //
  if (Variable == NULL) {
    return EFI_SUCCESS;
  }
  
  //
  // Variable is found.
  //
  VariableDevicePath = (EFI_DEVICE_PATH_PROTOCOL*)Variable;
  
  //
  // Check whether the specified DevicePath is contained in the Variable
  //
  Status = ConPlatformMatchDevicePaths (VariableDevicePath, 
                                        DevicePath, 
                                        NULL, 
                                        FALSE);
  if (Variable) {
    gBS->FreePool (Variable);
  }
  return Status;
}               

EFI_STATUS
ConPlatformUpdateDeviceVariable (
  IN  CHAR16                    *VariableName,
  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
  IN  BOOLEAN                   Append
  )
/*++

Routine Description:
  

Arguments:

Returns:

  None

--*/  
{
  EFI_STATUS                Status;
  UINT8                     *Variable;
  UINTN                     VariableSize;
  EFI_DEVICE_PATH_PROTOCOL  *VariableDevicePath;
  EFI_DEVICE_PATH_PROTOCOL  *NewVariableDevicePath;

  if (DevicePath == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  
  Variable = NULL;
  NewVariableDevicePath = NULL;
  
  //
  // Get Variable and its size according to variable name.
  // The memory for Variable is allocated within ConPlatformGetVaribleAndSize(),
  // it is the caller's responsibility to free the memory before return.
  //
  Variable = ConPlatformGetVariableAndSize (
               VariableName,
               &gEfiGlobalVariableGuid,
               &VariableSize  
               );
  VariableDevicePath = (EFI_DEVICE_PATH_PROTOCOL*)Variable;

  if (Append) {
    
    Status = ConPlatformMatchDevicePaths (VariableDevicePath, 
                                          DevicePath, 
                                          &NewVariableDevicePath,
                                          FALSE);
    
    if (!EFI_ERROR(Status)) {
      //
      // The device path has already in the variable
      //
      
      if (Variable) {
        gBS->FreePool (Variable);
      }
      if (NewVariableDevicePath) {
        gBS->FreePool (NewVariableDevicePath);
      }
      return EFI_SUCCESS;
    }
      
    //
    // Append DevicePath to the environment variable that 
    // is a multi-instance device path.
    //
    NewVariableDevicePath = EfiAppendDevicePathInstance (VariableDevicePath,
                                                          DevicePath);
    if (NewVariableDevicePath == NULL) {
      if (Variable) {
        gBS->FreePool (Variable);
      }
      return EFI_OUT_OF_RESOURCES;
    }

  } else {
    //
    // Remove DevicePath from the environment variable that 
    // is a multi-instance device path.
    //
    Status = ConPlatformMatchDevicePaths (VariableDevicePath, 
                                          DevicePath, 
                                          &NewVariableDevicePath,
                                          TRUE);
    if (EFI_ERROR (Status)) {
      if (Variable) {
        gBS->FreePool (Variable);
      }
      return Status;
    }
  }

  if (NewVariableDevicePath) {
    VariableSize = EfiDevicePathSize (NewVariableDevicePath);
  } else {
    VariableSize = 0;
  }

  Status = gRT->SetVariable (
                  VariableName, 
                  &gEfiGlobalVariableGuid,
                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                  VariableSize, 
                  NewVariableDevicePath
                  );

  if (NewVariableDevicePath) {
    gBS->FreePool (NewVariableDevicePath);
  }

  if (Variable) {
    gBS->FreePool (Variable);
  }

  return Status;
}

BOOLEAN
IsHotPlugDevice (
  EFI_HANDLE    DriverBindingHandle,
  EFI_HANDLE    ControllerHandle
  )
{
  EFI_STATUS    Status;
  
  //
  // HotPlugDeviceGuid indicates ControllerHandle stands for a hot plug device.
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle, 
                  &gEfiHotPlugDeviceGuid, 
                  NULL,
                  DriverBindingHandle,
                  ControllerHandle, 
                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                  );
  if (EFI_ERROR(Status)) {
    return FALSE;
  }
  
  return TRUE;
}

⌨️ 快捷键说明

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