/** Function for 'sermode' command. @param[in] ImageHandle Handle to the Image (NULL if Internal). @param[in] SystemTable Pointer to the System Table (NULL if Internal). **/ SHELL_STATUS EFIAPI ShellCommandRunSerMode ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; SHELL_STATUS ShellStatus; UINTN Index; UINTN NoHandles; EFI_HANDLE *Handles; EFI_PARITY_TYPE Parity; EFI_STOP_BITS_TYPE StopBits; UINTN HandleIdx; UINTN BaudRate; UINTN DataBits; UINTN Value; EFI_SERIAL_IO_PROTOCOL *SerialIo; LIST_ENTRY *Package; CHAR16 *ProblemParam; CONST CHAR16 *Temp; UINT64 Intermediate; ShellStatus = SHELL_SUCCESS; HandleIdx = 0; Parity = DefaultParity; Handles = NULL; NoHandles = 0; Index = 0; Package = NULL; Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); if (EFI_ERROR(Status)) { if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"sermode", ProblemParam); FreePool(ProblemParam); ShellStatus = SHELL_INVALID_PARAMETER; } else { ASSERT(FALSE); } } else { if (ShellCommandLineGetCount(Package) < 6 && ShellCommandLineGetCount(Package) > 2) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"sermode"); ShellStatus = SHELL_INVALID_PARAMETER; } else if (ShellCommandLineGetCount(Package) > 6) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"sermode"); ShellStatus = SHELL_INVALID_PARAMETER; } else { Temp = ShellCommandLineGetRawValue(Package, 1); if (Temp != NULL) { Status = ShellConvertStringToUint64(Temp, &Intermediate, TRUE, FALSE); HandleIdx = (UINTN)Intermediate; Temp = ShellCommandLineGetRawValue(Package, 2); if (Temp == NULL) { ShellStatus = DisplaySettings (HandleIdx, TRUE); goto Done; } } else { ShellStatus = DisplaySettings (0, FALSE); goto Done; } Temp = ShellCommandLineGetRawValue(Package, 2); if (Temp != NULL) { BaudRate = ShellStrToUintn(Temp); } else { ASSERT(FALSE); BaudRate = 0; } Temp = ShellCommandLineGetRawValue(Package, 3); if (Temp == NULL || StrLen(Temp)>1) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp); ShellStatus = SHELL_INVALID_PARAMETER; } else { switch(Temp[0]){ case 'd': case 'D': Parity = DefaultParity; break; case 'n': case 'N': Parity = NoParity; break; case 'e': case 'E': Parity = EvenParity; break; case 'o': case 'O': Parity = OddParity; break; case 'm': case 'M': Parity = MarkParity; break; case 's': case 'S': Parity = SpaceParity; break; default: ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } } Temp = ShellCommandLineGetRawValue(Package, 4); if (Temp != NULL) { DataBits = ShellStrToUintn(Temp); } else { // // make sure this is some number not in the list below. // DataBits = 0; } switch (DataBits) { case 4: case 7: case 8: break; default: ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } Temp = ShellCommandLineGetRawValue(Package, 5); Value = ShellStrToUintn(Temp); switch (Value) { case 0: StopBits = DefaultStopBits; break; case 1: StopBits = OneStopBit; break; case 2: StopBits = TwoStopBits; break; case 15: StopBits = OneFiveStopBits; break; default: ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Handles); if (EFI_ERROR (Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_NO_FOUND), gShellDebug1HiiHandle, L"sermode"); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } for (Index = 0; Index < NoHandles; Index++) { if (ConvertHandleIndexToHandle (HandleIdx) != Handles[Index]) { continue; } Status = gBS->HandleProtocol (Handles[Index], &gEfiSerialIoProtocolGuid, (VOID**)&SerialIo); if (!EFI_ERROR (Status)) { Status = SerialIo->SetAttributes ( SerialIo, (UINT64) BaudRate, SerialIo->Mode->ReceiveFifoDepth, SerialIo->Mode->Timeout, Parity, (UINT8) DataBits, StopBits ); if (EFI_ERROR (Status)) { if (Status == EFI_INVALID_PARAMETER) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_UNSUPPORTED), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex(Handles[Index])); ShellStatus = SHELL_UNSUPPORTED; } else if (Status == EFI_DEVICE_ERROR) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_DEV_ERROR), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex(Handles[Index])); ShellStatus = SHELL_ACCESS_DENIED; } else { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_FAIL), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex(Handles[Index])); ShellStatus = SHELL_ACCESS_DENIED; } } else { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_HANDLE), gShellDebug1HiiHandle, ConvertHandleToHandleIndex(Handles[Index])); } break; } } } } if (ShellStatus == SHELL_SUCCESS && Index == NoHandles) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_BAD_HANDLE), gShellDebug1HiiHandle, L"sermode", HandleIdx); ShellStatus = SHELL_INVALID_PARAMETER; } Done: if (Package != NULL) { ShellCommandLineFreeVarList (Package); } if (Handles != NULL) { FreePool (Handles); } return ShellStatus; }
STATIC EFI_STATUS EFIAPI WinNtSerialIoDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) /*++ Routine Description: Arguments: Returns: None --*/ // TODO: This - add argument and description to function comment // TODO: Handle - add argument and description to function comment // TODO: RemainingDevicePath - add argument and description to function comment // TODO: EFI_SUCCESS - add return value to function comment // TODO: EFI_SUCCESS - add return value to function comment { EFI_STATUS Status; EFI_WIN_NT_IO_PROTOCOL *WinNtIo; WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; HANDLE NtHandle; UART_DEVICE_PATH Node; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; UINTN EntryCount; UINTN Index; EFI_SERIAL_IO_PROTOCOL *SerialIo; Private = NULL; NtHandle = INVALID_HANDLE_VALUE; // // Grab the protocols we need // Status = gBS->OpenProtocol ( Handle, &gEfiDevicePathProtocolGuid, &ParentDevicePath, This->DriverBindingHandle, Handle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { return Status; } // // Grab the IO abstraction we need to get any work done // Status = gBS->OpenProtocol ( Handle, &gEfiWinNtIoProtocolGuid, &WinNtIo, This->DriverBindingHandle, Handle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { gBS->CloseProtocol ( Handle, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Handle ); return Status; } if (Status == EFI_ALREADY_STARTED) { if (RemainingDevicePath == NULL) { return EFI_SUCCESS; } // // Make sure a child handle does not already exist. This driver can only // produce one child per serial port. // Status = gBS->OpenProtocolInformation ( Handle, &gEfiWinNtIoProtocolGuid, &OpenInfoBuffer, &EntryCount ); if (EFI_ERROR (Status)) { return Status; } Status = EFI_ALREADY_STARTED; for (Index = 0; Index < EntryCount; Index++) { if (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) { Status = gBS->OpenProtocol ( OpenInfoBuffer[Index].ControllerHandle, &gEfiSerialIoProtocolGuid, &SerialIo, This->DriverBindingHandle, Handle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (!EFI_ERROR (Status)) { EfiCopyMem (&Node, RemainingDevicePath, sizeof (UART_DEVICE_PATH)); Status = SerialIo->SetAttributes ( SerialIo, Node.BaudRate, SerialIo->Mode->ReceiveFifoDepth, SerialIo->Mode->Timeout, Node.Parity, Node.DataBits, Node.StopBits ); } break; } } gBS->FreePool (OpenInfoBuffer); return Status; } // // Check to see if we can access the hardware device. If it's Open in NT we // will not get access. // NtHandle = WinNtIo->WinNtThunk->CreateFile ( WinNtIo->EnvString, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); if (NtHandle == INVALID_HANDLE_VALUE) { Status = EFI_DEVICE_ERROR; goto Error; } // // Construct Private data // Status = gBS->AllocatePool ( EfiBootServicesData, sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA), &Private ); if (EFI_ERROR (Status)) { goto Error; } // // This signature must be valid before any member function is called // Private->Signature = WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE; Private->NtHandle = NtHandle; Private->ControllerHandle = Handle; Private->Handle = NULL; Private->WinNtThunk = WinNtIo->WinNtThunk; Private->ParentDevicePath = ParentDevicePath; Private->ControllerNameTable = NULL; Private->SoftwareLoopbackEnable = FALSE; Private->HardwareLoopbackEnable = FALSE; Private->HardwareFlowControl = FALSE; Private->Fifo.First = 0; Private->Fifo.Last = 0; Private->Fifo.Surplus = SERIAL_MAX_BUFFER_SIZE; EfiLibAddUnicodeString ( LANGUAGE_CODE_ENGLISH, gWinNtSerialIoComponentName.SupportedLanguages, &Private->ControllerNameTable, WinNtIo->EnvString ); Private->SerialIo.Revision = SERIAL_IO_INTERFACE_REVISION; Private->SerialIo.Reset = WinNtSerialIoReset; Private->SerialIo.SetAttributes = WinNtSerialIoSetAttributes; Private->SerialIo.SetControl = WinNtSerialIoSetControl; Private->SerialIo.GetControl = WinNtSerialIoGetControl; Private->SerialIo.Write = WinNtSerialIoWrite; Private->SerialIo.Read = WinNtSerialIoRead; Private->SerialIo.Mode = &Private->SerialIoMode; if (RemainingDevicePath != NULL) { // // Match the configuration of the RemainingDevicePath. IsHandleSupported() // already checked to make sure the RemainingDevicePath contains settings // that we can support. // EfiCopyMem (&Private->UartDevicePath, RemainingDevicePath, sizeof (UART_DEVICE_PATH)); } else { // // Build the device path by appending the UART node to the ParentDevicePath // from the WinNtIo handle. The Uart setings are zero here, since // SetAttribute() will update them to match the default setings. // EfiZeroMem (&Private->UartDevicePath, sizeof (UART_DEVICE_PATH)); Private->UartDevicePath.Header.Type = MESSAGING_DEVICE_PATH; Private->UartDevicePath.Header.SubType = MSG_UART_DP; SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath, sizeof (UART_DEVICE_PATH)); } // // Build the device path by appending the UART node to the ParentDevicePath // from the WinNtIo handle. The Uart setings are zero here, since // SetAttribute() will update them to match the current setings. // Private->DevicePath = EfiAppendDevicePathNode ( ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath ); if (Private->DevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; } // // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults. // Private->SerialIoMode.ControlMask = SERIAL_CONTROL_MASK; Private->SerialIoMode.Timeout = SERIAL_TIMEOUT_DEFAULT; Private->SerialIoMode.BaudRate = Private->UartDevicePath.BaudRate; Private->SerialIoMode.ReceiveFifoDepth = SERIAL_FIFO_DEFAULT; Private->SerialIoMode.DataBits = Private->UartDevicePath.DataBits; Private->SerialIoMode.Parity = Private->UartDevicePath.Parity; Private->SerialIoMode.StopBits = Private->UartDevicePath.StopBits; // // Issue a reset to initialize the COM port // Status = Private->SerialIo.Reset (&Private->SerialIo); if (EFI_ERROR (Status)) { goto Error; } // // Create new child handle // Status = gBS->InstallMultipleProtocolInterfaces ( &Private->Handle, &gEfiSerialIoProtocolGuid, &Private->SerialIo, &gEfiDevicePathProtocolGuid, Private->DevicePath, NULL ); if (EFI_ERROR (Status)) { goto Error; } // // Open For Child Device // Status = gBS->OpenProtocol ( Handle, &gEfiWinNtIoProtocolGuid, &WinNtIo, This->DriverBindingHandle, Private->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { goto Error; } return EFI_SUCCESS; Error: // // Use the Stop() function to free all resources allocated in Start() // if (Private != NULL) { if (Private->Handle != NULL) { This->Stop (This, Handle, 1, &Private->Handle); } else { if (NtHandle != INVALID_HANDLE_VALUE) { Private->WinNtThunk->CloseHandle (NtHandle); } if (Private->DevicePath != NULL) { gBS->FreePool (Private->DevicePath); } EfiLibFreeUnicodeStringTable (Private->ControllerNameTable); gBS->FreePool (Private); } } This->Stop (This, Handle, 0, NULL); return Status; }
/** Timer handler to poll the key from serial. @param Event Indicates the event that invoke this function. @param Context Indicates the calling context. **/ VOID EFIAPI TerminalConInTimerHandler ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; TERMINAL_DEV *TerminalDevice; UINT32 Control; UINT8 Input; EFI_SERIAL_IO_MODE *Mode; EFI_SERIAL_IO_PROTOCOL *SerialIo; UINTN SerialInTimeOut; TerminalDevice = (TERMINAL_DEV *) Context; SerialIo = TerminalDevice->SerialIo; if (SerialIo == NULL) { return ; } // // if current timeout value for serial device is not identical with // the value saved in TERMINAL_DEV structure, then recalculate the // timeout value again and set serial attribute according to this value. // Mode = SerialIo->Mode; if (Mode->Timeout != TerminalDevice->SerialInTimeOut) { SerialInTimeOut = 0; if (Mode->BaudRate != 0) { // // According to BAUD rate to calculate the timeout value. // SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate; } Status = SerialIo->SetAttributes ( SerialIo, Mode->BaudRate, Mode->ReceiveFifoDepth, (UINT32) SerialInTimeOut, (EFI_PARITY_TYPE) (Mode->Parity), (UINT8) Mode->DataBits, (EFI_STOP_BITS_TYPE) (Mode->StopBits) ); if (EFI_ERROR (Status)) { TerminalDevice->SerialInTimeOut = 0; } else { TerminalDevice->SerialInTimeOut = SerialInTimeOut; } } // // Check whether serial buffer is empty. // Status = SerialIo->GetControl (SerialIo, &Control); if ((Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) == 0) { // // Fetch all the keys in the serial buffer, // and insert the byte stream into RawFIFO. // while (!IsRawFiFoFull (TerminalDevice)) { Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input); if (EFI_ERROR (Status)) { if (Status == EFI_DEVICE_ERROR) { REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_INPUT_ERROR), TerminalDevice->DevicePath ); } break; } RawFiFoInsertOneKey (TerminalDevice, Input); } } // // Translate all the raw data in RawFIFO into EFI Key, // according to different terminal type supported. // TranslateRawDataToEfiKey (TerminalDevice); }
EFI_STATUS EFIAPI WinNtSerialIoDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) /*++ Routine Description: Arguments: Returns: None --*/ // TODO: This - add argument and description to function comment // TODO: Handle - add argument and description to function comment // TODO: RemainingDevicePath - add argument and description to function comment // TODO: EFI_SUCCESS - add return value to function comment // TODO: EFI_SUCCESS - add return value to function comment { EFI_STATUS Status; EFI_WIN_NT_IO_PROTOCOL *WinNtIo; WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; HANDLE NtHandle; UART_DEVICE_PATH UartNode; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; UINTN EntryCount; UINTN Index; EFI_SERIAL_IO_PROTOCOL *SerialIo; UART_DEVICE_PATH *Uart; UINT32 FlowControlMap; UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; UINT32 Control; Private = NULL; NtHandle = INVALID_HANDLE_VALUE; // // Get the Parent Device Path // Status = gBS->OpenProtocol ( Handle, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Handle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { return Status; } // // Grab the IO abstraction we need to get any work done // Status = gBS->OpenProtocol ( Handle, &gEfiWinNtIoProtocolGuid, (VOID **) &WinNtIo, This->DriverBindingHandle, Handle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { gBS->CloseProtocol ( Handle, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Handle ); return Status; } if (Status == EFI_ALREADY_STARTED) { if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) { // // If RemainingDevicePath is NULL or is the End of Device Path Node // return EFI_SUCCESS; } // // Make sure a child handle does not already exist. This driver can only // produce one child per serial port. // Status = gBS->OpenProtocolInformation ( Handle, &gEfiWinNtIoProtocolGuid, &OpenInfoBuffer, &EntryCount ); if (EFI_ERROR (Status)) { return Status; } Status = EFI_ALREADY_STARTED; for (Index = 0; Index < EntryCount; Index++) { if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { Status = gBS->OpenProtocol ( OpenInfoBuffer[Index].ControllerHandle, &gEfiSerialIoProtocolGuid, (VOID **) &SerialIo, This->DriverBindingHandle, Handle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (!EFI_ERROR (Status)) { Uart = (UART_DEVICE_PATH *) RemainingDevicePath; Status = SerialIo->SetAttributes ( SerialIo, Uart->BaudRate, SerialIo->Mode->ReceiveFifoDepth, SerialIo->Mode->Timeout, (EFI_PARITY_TYPE) Uart->Parity, Uart->DataBits, (EFI_STOP_BITS_TYPE) Uart->StopBits ); FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart); if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) { Status = SerialIo->GetControl (SerialIo, &Control); if (!EFI_ERROR (Status)) { if (FlowControl->FlowControlMap == UART_FLOW_CONTROL_HARDWARE) { Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; } else { Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; } // // Clear the bits that are not allowed to pass to SetControl // Control &= (EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE); Status = SerialIo->SetControl (SerialIo, Control); } } } break; } } FreePool (OpenInfoBuffer); return Status; } FlowControl = NULL; FlowControlMap = 0; if (RemainingDevicePath == NULL) { // // Build the device path by appending the UART node to the ParentDevicePath // from the WinNtIo handle. The Uart setings are zero here, since // SetAttribute() will update them to match the default setings. // ZeroMem (&UartNode, sizeof (UART_DEVICE_PATH)); UartNode.Header.Type = MESSAGING_DEVICE_PATH; UartNode.Header.SubType = MSG_UART_DP; SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &UartNode, sizeof (UART_DEVICE_PATH)); } else if (!IsDevicePathEnd (RemainingDevicePath)) { // // If RemainingDevicePath isn't the End of Device Path Node, // only scan the specified device by RemainingDevicePath // // // Match the configuration of the RemainingDevicePath. IsHandleSupported() // already checked to make sure the RemainingDevicePath contains settings // that we can support. // CopyMem (&UartNode, RemainingDevicePath, sizeof (UART_DEVICE_PATH)); FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath); if (IsUartFlowControlNode (FlowControl)) { FlowControlMap = FlowControl->FlowControlMap; } else { FlowControl = NULL; } } else { // // If RemainingDevicePath is the End of Device Path Node, // skip enumerate any device and return EFI_SUCESSS // return EFI_SUCCESS; } // // Check to see if we can access the hardware device. If it's Open in NT we // will not get access. // NtHandle = WinNtIo->WinNtThunk->CreateFile ( WinNtIo->EnvString, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); if (NtHandle == INVALID_HANDLE_VALUE) { Status = EFI_DEVICE_ERROR; goto Error; } // // Construct Private data // Private = AllocatePool (sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA)); if (Private == NULL) { goto Error; } // // This signature must be valid before any member function is called // Private->Signature = WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE; Private->NtHandle = NtHandle; Private->ControllerHandle = Handle; Private->Handle = NULL; Private->WinNtThunk = WinNtIo->WinNtThunk; Private->ParentDevicePath = ParentDevicePath; Private->ControllerNameTable = NULL; Private->SoftwareLoopbackEnable = FALSE; Private->HardwareLoopbackEnable = FALSE; Private->HardwareFlowControl = (BOOLEAN) (FlowControlMap == UART_FLOW_CONTROL_HARDWARE); Private->Fifo.First = 0; Private->Fifo.Last = 0; Private->Fifo.Surplus = SERIAL_MAX_BUFFER_SIZE; CopyMem (&Private->UartDevicePath, &UartNode, sizeof (UART_DEVICE_PATH)); AddUnicodeString2 ( "eng", gWinNtSerialIoComponentName.SupportedLanguages, &Private->ControllerNameTable, WinNtIo->EnvString, TRUE ); AddUnicodeString2 ( "en", gWinNtSerialIoComponentName2.SupportedLanguages, &Private->ControllerNameTable, WinNtIo->EnvString, FALSE ); Private->SerialIo.Revision = SERIAL_IO_INTERFACE_REVISION; Private->SerialIo.Reset = WinNtSerialIoReset; Private->SerialIo.SetAttributes = WinNtSerialIoSetAttributes; Private->SerialIo.SetControl = WinNtSerialIoSetControl; Private->SerialIo.GetControl = WinNtSerialIoGetControl; Private->SerialIo.Write = WinNtSerialIoWrite; Private->SerialIo.Read = WinNtSerialIoRead; Private->SerialIo.Mode = &Private->SerialIoMode; // // Build the device path by appending the UART node to the ParentDevicePath // from the WinNtIo handle. The Uart setings are zero here, since // SetAttribute() will update them to match the current setings. // Private->DevicePath = AppendDevicePathNode ( ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath ); // // Only produce the FlowControl node when remaining device path has it // if (FlowControl != NULL) { TempDevicePath = Private->DevicePath; if (TempDevicePath != NULL) { Private->DevicePath = AppendDevicePathNode ( TempDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) FlowControl ); FreePool (TempDevicePath); } } if (Private->DevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; } // // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults. // Private->SerialIoMode.ControlMask = SERIAL_CONTROL_MASK; Private->SerialIoMode.Timeout = SERIAL_TIMEOUT_DEFAULT; Private->SerialIoMode.BaudRate = Private->UartDevicePath.BaudRate; Private->SerialIoMode.ReceiveFifoDepth = SERIAL_FIFO_DEFAULT; Private->SerialIoMode.DataBits = Private->UartDevicePath.DataBits; Private->SerialIoMode.Parity = Private->UartDevicePath.Parity; Private->SerialIoMode.StopBits = Private->UartDevicePath.StopBits; // // Issue a reset to initialize the COM port // Status = Private->SerialIo.Reset (&Private->SerialIo); if (EFI_ERROR (Status)) { goto Error; } // // Create new child handle // Status = gBS->InstallMultipleProtocolInterfaces ( &Private->Handle, &gEfiSerialIoProtocolGuid, &Private->SerialIo, &gEfiDevicePathProtocolGuid, Private->DevicePath, NULL ); if (EFI_ERROR (Status)) { goto Error; } // // Open For Child Device // Status = gBS->OpenProtocol ( Handle, &gEfiWinNtIoProtocolGuid, (VOID **) &WinNtIo, This->DriverBindingHandle, Private->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { goto Error; } return EFI_SUCCESS; Error: // // Use the Stop() function to free all resources allocated in Start() // if (Private != NULL) { if (Private->Handle != NULL) { This->Stop (This, Handle, 1, &Private->Handle); } else { if (NtHandle != INVALID_HANDLE_VALUE) { Private->WinNtThunk->CloseHandle (NtHandle); } if (Private->DevicePath != NULL) { FreePool (Private->DevicePath); } FreeUnicodeStringTable (Private->ControllerNameTable); FreePool (Private); } } This->Stop (This, Handle, 0, NULL); return Status; }