terminal.c

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

C
1,176
字号
               This->DriverBindingHandle, 
               ChildHandleBuffer[Index],
               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
               );
      } else {
        
        if (TerminalDevice->ControllerNameTable) {
          EfiLibFreeUnicodeStringTable (TerminalDevice->ControllerNameTable);
        }
        
        Status = gBS->OpenProtocol (
                ChildHandleBuffer[Index], 
                &gEfiHotPlugDeviceGuid, 
                NULL,
                This->DriverBindingHandle,
                Controller, 
                EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                );
        if (!EFI_ERROR (Status)) {
          Status = gBS->UninstallMultipleProtocolInterfaces (
                          ChildHandleBuffer[Index],
                          &gEfiHotPlugDeviceGuid, NULL,
                          NULL
                          );
        } else {
          Status = EFI_SUCCESS;
        }
        gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);
        gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);
        gBS->FreePool (TerminalDevice);
      }
    }

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

  if (!AllChildrenStopped) {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

VOID
TerminalUpdateConsoleDevVariable (
  IN CHAR16                    *VariableName,
  IN EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath
  )

{
  EFI_STATUS                Status;
  UINTN                     VariableSize;
  UINT8                     TerminalType;
  EFI_DEVICE_PATH_PROTOCOL  *Variable;
  EFI_DEVICE_PATH_PROTOCOL  *NewVariable;
  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
  
  Variable = NULL;

  //
  // Get global variable and its size according to the name given.
  //
  Variable = TerminalGetVariableAndSize (
               VariableName,
               &gEfiGlobalVariableGuid,
               &VariableSize  
               );
  //
  // Append terminal device path onto the variable.
  //               
  for (TerminalType = PcAnsiType; TerminalType <= VTUTF8Type; TerminalType++) {
    SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);
    NewVariable = EfiAppendDevicePathInstance (Variable, TempDevicePath);
    if (Variable != NULL) {
      gBS->FreePool (Variable);
    }
    if (TempDevicePath != NULL) {
      gBS->FreePool (TempDevicePath);
    }
    Variable = NewVariable;
  }

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

VOID
TerminalRemoveConsoleDevVariable (
  IN CHAR16                    *VariableName,
  IN EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath
  )

{
  EFI_STATUS                Status;
  BOOLEAN                   FoundOne;
  BOOLEAN                   Match;
  UINTN                     VariableSize;
  UINTN                     InstanceSize;
  UINT8                     TerminalType;
  EFI_DEVICE_PATH_PROTOCOL  *Instance;
  EFI_DEVICE_PATH_PROTOCOL  *Variable;
  EFI_DEVICE_PATH_PROTOCOL  *OriginalVariable;
  EFI_DEVICE_PATH_PROTOCOL  *NewVariable;
  EFI_DEVICE_PATH_PROTOCOL  *SavedNewVariable;
  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
  
  Variable = NULL;
  Instance = NULL;
  
  //
  // Get global variable and its size according to the name given.
  //
  Variable = TerminalGetVariableAndSize (
               VariableName,
               &gEfiGlobalVariableGuid,
               &VariableSize  
               );
  if (Variable == NULL) {
    return;
  }

  FoundOne         = FALSE;
  OriginalVariable = Variable;
  NewVariable      = NULL;

  //
  // Get first device path instance from Variable
  //
  Instance = EfiDevicePathInstance (&Variable, &InstanceSize);
  if (Instance == NULL) {
    gBS->FreePool (OriginalVariable);
    return;
  }
  //
  // Loop through all the device path instances of Variable
  //
  do {

    //
    // Loop through all the terminal types that this driver supports
    //               
    Match = FALSE;
    for (TerminalType = PcAnsiType; TerminalType <= VTUTF8Type; 
          TerminalType++) {
            
      SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);

      //
      // Compare the genterated device path to the current device path instance
      //
      if (TempDevicePath != NULL) {
        if (EfiCompareMem (Instance, TempDevicePath, InstanceSize) == 0) {
          Match = TRUE;
          FoundOne = TRUE;
        }
        gBS->FreePool (TempDevicePath);
      }
    }

    //
    // If a match was not found, then keep the current device path instance
    //
    if (!Match) {
      SavedNewVariable = NewVariable;
      NewVariable = EfiAppendDevicePathInstance (NewVariable, Instance);
      if (SavedNewVariable != NULL) {
        gBS->FreePool (SavedNewVariable);
      }
    }

    //
    // Get next device path instance from Variable
    //
    gBS->FreePool(Instance);
    Instance = EfiDevicePathInstance (&Variable, &InstanceSize);
  } while (Instance != NULL);

  gBS->FreePool (OriginalVariable);

  if (FoundOne) {
    VariableSize = EfiDevicePathSize (NewVariable);
  
    Status = gRT->SetVariable (
                VariableName,
                &gEfiGlobalVariableGuid,
                EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                VariableSize,
                NewVariable
                );
  }
}

VOID *
TerminalGetVariableAndSize (
  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;
  UINTN         BufferSize;
  VOID          *Buffer;

  Buffer = NULL;

  //
  // Pass in a small size buffer to find the actual variable size.
  //
  BufferSize = 1;
  Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, &Buffer); 
  if (EFI_ERROR(Status)) {
    *VariableSize = 0;
    return NULL;
  }
  
  Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
  
  if (Status == EFI_SUCCESS) {
    *VariableSize = BufferSize;
    return Buffer;
  
  } else if (Status == EFI_BUFFER_TOO_SMALL) {
    //
    // Allocate the buffer to return
    //
    gBS->FreePool (Buffer);
    Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, &Buffer); 
    if (EFI_ERROR (Status)) {
      *VariableSize = 0;
      return NULL;
    }

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

  *VariableSize = BufferSize;
  return Buffer;
}


EFI_STATUS
SetTerminalDevicePath (
  IN  UINT8                       TerminalType,
  IN  EFI_DEVICE_PATH_PROTOCOL    *ParentDevicePath,
  OUT EFI_DEVICE_PATH_PROTOCOL    **TerminalDevicePath
  )
{ 
  VENDOR_DEVICE_PATH  Node;
  
  *TerminalDevicePath = NULL;
  Node.Header.Type    = MESSAGING_DEVICE_PATH;
  Node.Header.SubType = MSG_VENDOR_DP;
  
  //
  // generate terminal device path node according to terminal type.
  //  
  switch (TerminalType) {
    
    case PcAnsiType:
      EfiCopyMem (
            &Node.Guid, 
            &gEfiPcAnsiGuid, 
            sizeof(EFI_GUID)
            );
      break;
    
    case VT100Type:
      EfiCopyMem (
            &Node.Guid, 
            &gEfiVT100Guid, 
            sizeof(EFI_GUID)
            );
      break;
      
    case VT100PlusType:
      EfiCopyMem (
            &Node.Guid, 
            &gEfiVT100PlusGuid, 
            sizeof(EFI_GUID)
            );
      break;
      
    case VTUTF8Type:
      EfiCopyMem (
            &Node.Guid, 
            &gEfiVTUTF8Guid, 
            sizeof(EFI_GUID)
            );
      break;
    
    default:
      return EFI_UNSUPPORTED;
      break;
  }
  
  SetDevicePathNodeLength (
            &Node.Header, 
            sizeof(VENDOR_DEVICE_PATH)
            );
  //
  // append the terminal node onto parent device path
  // to generate a complete terminal device path.
  //
  *TerminalDevicePath = EfiAppendDevicePathNode (
                          ParentDevicePath, 
                          (EFI_DEVICE_PATH_PROTOCOL *)&Node
                          );
  if (*TerminalDevicePath == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  
  return EFI_SUCCESS;
                               
}                               

VOID
InitializeRawFiFo (
  IN  TERMINAL_DEV  *TerminalDevice
  )
{
  //
  // Make the raw fifo empty.
  //
  TerminalDevice->RawFiFo.Head = TerminalDevice->RawFiFo.Tail;
}

VOID
InitializeUnicodeFiFo (  
  IN  TERMINAL_DEV  *TerminalDevice
  )
{
  //
  // Make the unicode fifo empty
  //
  TerminalDevice->UnicodeFiFo.Head = TerminalDevice->UnicodeFiFo.Tail;
}  

VOID 
InitializeEfiKeyFiFo (
  IN  TERMINAL_DEV  *TerminalDevice
  )
{
  //
  // Make the efi key fifo empty
  //
  TerminalDevice->EfiKeyFiFo.Head = TerminalDevice->EfiKeyFiFo.Tail;  
}  

⌨️ 快捷键说明

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