From 95276127e373f2e2fb2a208ff77267422a197d9f Mon Sep 17 00:00:00 2001 From: xgu3 Date: Thu, 5 Jul 2007 07:05:28 +0000 Subject: [PATCH] Check in following modules, DxeIpl ConPlatform ConSplitter GraphicsConsole Terminal DevicePath git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3069 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Include/Protocol/FrameworkHii.h | 950 +++++ MdeModulePkg/Core/DxeIplPeim/CommonHeader.h | 56 + MdeModulePkg/Core/DxeIplPeim/DxeIpl.dxs | 28 + MdeModulePkg/Core/DxeIplPeim/DxeIpl.h | 117 + MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 171 + MdeModulePkg/Core/DxeIplPeim/DxeIpl.msa | 168 + MdeModulePkg/Core/DxeIplPeim/DxeLoad.c | 980 +++++ .../Core/DxeIplPeim/Ia32/DxeLoadFunc.c | 136 + MdeModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c | 117 + .../Core/DxeIplPeim/Ia32/VirtualMemory.c | 173 + .../Core/DxeIplPeim/Ia32/VirtualMemory.h | 112 + .../Core/DxeIplPeim/Ipf/DxeLoadFunc.c | 77 + MdeModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c | 77 + .../Core/DxeIplPeim/X64/DxeLoadFunc.c | 65 + .../Include/Common/DecompressLibraryHob.h | 47 + MdeModulePkg/MdeModulePkg.dec | 5 +- MdeModulePkg/MdeModulePkg.dsc | 23 + .../Console/ConPlatformDxe/CommonHeader.h | 54 + .../Console/ConPlatformDxe/ComponentName.c | 146 + .../Console/ConPlatformDxe/ComponentName.h | 45 + .../Console/ConPlatformDxe/ConPlatform.c | 950 +++++ .../Console/ConPlatformDxe/ConPlatform.h | 132 + .../Console/ConPlatformDxe/ConPlatform.inf | 112 + .../Console/ConPlatformDxe/ConPlatform.msa | 135 + .../Console/ConSplitterDxe/CommonHeader.h | 61 + .../Console/ConSplitterDxe/ComponentName.c | 485 +++ .../Console/ConSplitterDxe/ConSplitter.c | 3467 +++++++++++++++++ .../Console/ConSplitterDxe/ConSplitter.h | 667 ++++ .../Console/ConSplitterDxe/ConSplitter.inf | 120 + .../Console/ConSplitterDxe/ConSplitter.msa | 126 + .../ConSplitterDxe/ConSplitterGraphics.c | 1222 ++++++ .../Console/GraphicsConsoleDxe/CommonHeader.h | 47 + .../GraphicsConsoleDxe/ComponentName.c | 144 + .../GraphicsConsoleDxe/ComponentName.h | 56 + .../Console/GraphicsConsoleDxe/EntryPoint.c | 56 + .../GraphicsConsoleDxe/GraphicsConsole.c | 1826 +++++++++ .../GraphicsConsoleDxe/GraphicsConsole.h | 192 + .../GraphicsConsoleDxe/GraphicsConsole.inf | 110 + .../GraphicsConsoleDxe/GraphicsConsole.msa | 92 + .../Console/GraphicsConsoleDxe/LaffStd.c | 295 ++ .../Console/TerminalDxe/CommonHeader.h | 51 + .../Console/TerminalDxe/ComponentName.c | 200 + .../Console/TerminalDxe/EntryPoint.c | 56 + .../Universal/Console/TerminalDxe/Terminal.c | 1194 ++++++ .../Universal/Console/TerminalDxe/Terminal.h | 554 +++ .../Console/TerminalDxe/Terminal.inf | 117 + .../Console/TerminalDxe/Terminal.msa | 129 + .../Console/TerminalDxe/TerminalConIn.c | 1184 ++++++ .../Console/TerminalDxe/TerminalConOut.c | 1002 +++++ .../Universal/Console/TerminalDxe/ansi.c | 73 + .../Universal/Console/TerminalDxe/vtutf8.c | 275 ++ .../Universal/DevicePathDxe/CommonHeader.h | 44 + .../Universal/DevicePathDxe/DevicePath.c | 114 + .../Universal/DevicePathDxe/DevicePath.h | 412 ++ .../Universal/DevicePathDxe/DevicePath.inf | 122 + .../Universal/DevicePathDxe/DevicePath.msa | 117 + .../DevicePathDxe/DevicePathFromText.c | 2375 +++++++++++ .../DevicePathDxe/DevicePathToText.c | 1503 +++++++ .../DevicePathDxe/DevicePathUtilities.c | 216 + .../Nt32PeCoffLoaderLib/CommonHeader.h | 5 +- .../Nt32PeCoffLoaderLib.inf | 1 + Nt32Pkg/Nt32Pkg.dec | 2 + Nt32Pkg/Nt32Pkg.dsc | 20 +- 63 files changed, 23601 insertions(+), 7 deletions(-) create mode 100644 IntelFrameworkPkg/Include/Protocol/FrameworkHii.h create mode 100644 MdeModulePkg/Core/DxeIplPeim/CommonHeader.h create mode 100644 MdeModulePkg/Core/DxeIplPeim/DxeIpl.dxs create mode 100644 MdeModulePkg/Core/DxeIplPeim/DxeIpl.h create mode 100644 MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf create mode 100644 MdeModulePkg/Core/DxeIplPeim/DxeIpl.msa create mode 100644 MdeModulePkg/Core/DxeIplPeim/DxeLoad.c create mode 100644 MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c create mode 100644 MdeModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c create mode 100644 MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.c create mode 100644 MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h create mode 100644 MdeModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c create mode 100644 MdeModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c create mode 100644 MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c create mode 100644 MdeModulePkg/Include/Common/DecompressLibraryHob.h create mode 100644 MdeModulePkg/Universal/Console/ConPlatformDxe/CommonHeader.h create mode 100644 MdeModulePkg/Universal/Console/ConPlatformDxe/ComponentName.c create mode 100644 MdeModulePkg/Universal/Console/ConPlatformDxe/ComponentName.h create mode 100644 MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.c create mode 100644 MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.h create mode 100644 MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.inf create mode 100644 MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.msa create mode 100644 MdeModulePkg/Universal/Console/ConSplitterDxe/CommonHeader.h create mode 100644 MdeModulePkg/Universal/Console/ConSplitterDxe/ComponentName.c create mode 100644 MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c create mode 100644 MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h create mode 100644 MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.inf create mode 100644 MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.msa create mode 100644 MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c create mode 100644 MdeModulePkg/Universal/Console/GraphicsConsoleDxe/CommonHeader.h create mode 100644 MdeModulePkg/Universal/Console/GraphicsConsoleDxe/ComponentName.c create mode 100644 MdeModulePkg/Universal/Console/GraphicsConsoleDxe/ComponentName.h create mode 100644 MdeModulePkg/Universal/Console/GraphicsConsoleDxe/EntryPoint.c create mode 100644 MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c create mode 100644 MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h create mode 100644 MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.inf create mode 100644 MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.msa create mode 100644 MdeModulePkg/Universal/Console/GraphicsConsoleDxe/LaffStd.c create mode 100644 MdeModulePkg/Universal/Console/TerminalDxe/CommonHeader.h create mode 100644 MdeModulePkg/Universal/Console/TerminalDxe/ComponentName.c create mode 100644 MdeModulePkg/Universal/Console/TerminalDxe/EntryPoint.c create mode 100644 MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c create mode 100644 MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h create mode 100644 MdeModulePkg/Universal/Console/TerminalDxe/Terminal.inf create mode 100644 MdeModulePkg/Universal/Console/TerminalDxe/Terminal.msa create mode 100644 MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c create mode 100644 MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c create mode 100644 MdeModulePkg/Universal/Console/TerminalDxe/ansi.c create mode 100644 MdeModulePkg/Universal/Console/TerminalDxe/vtutf8.c create mode 100644 MdeModulePkg/Universal/DevicePathDxe/CommonHeader.h create mode 100644 MdeModulePkg/Universal/DevicePathDxe/DevicePath.c create mode 100644 MdeModulePkg/Universal/DevicePathDxe/DevicePath.h create mode 100644 MdeModulePkg/Universal/DevicePathDxe/DevicePath.inf create mode 100644 MdeModulePkg/Universal/DevicePathDxe/DevicePath.msa create mode 100644 MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c create mode 100644 MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c create mode 100644 MdeModulePkg/Universal/DevicePathDxe/DevicePathUtilities.c diff --git a/IntelFrameworkPkg/Include/Protocol/FrameworkHii.h b/IntelFrameworkPkg/Include/Protocol/FrameworkHii.h new file mode 100644 index 0000000000..ae3d3799d8 --- /dev/null +++ b/IntelFrameworkPkg/Include/Protocol/FrameworkHii.h @@ -0,0 +1,950 @@ +/** @file + This file defines the Human Interface Infrastructure protocol which will + be used by resources which want to publish IFR/Font/String data and have it + collected by the Configuration engine. + + Copyright (c) 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Module Name: FrameworkHii.h + + @par Revision Reference: + This protocol is defined in HII spec 0.92. + +**/ + +#ifndef _FRAMEWORK_HII_H_ +#define _FRAMEWORK_HII_H_ + +#include + +// +// To get EFI_GRAPHICS_OUTPUT_BLT_PIXEL, +// is defined in MdePkg/Protocol/GraphicsOutput.h +// +#include + +#define EFI_HII_PROTOCOL_GUID \ + { \ + 0xd7ad636e, 0xb997, 0x459b, {0xbf, 0x3f, 0x88, 0x46, 0x89, 0x79, 0x80, 0xe1} \ + } + +// BugBug: +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// If UGA goes away we need to put this some place. I'm not sure where? +// +//typedef struct { +// UINT8 Blue; +// UINT8 Green; +// UINT8 Red; +// UINT8 Reserved; +//} EFI_UGA_PIXEL; + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// + +typedef struct _EFI_HII_PROTOCOL EFI_HII_PROTOCOL; + +// +// Global definition +// +#define NARROW_CHAR 0xFFF0 +#define WIDE_CHAR 0xFFF1 +#define NON_BREAKING_CHAR 0xFFF2 +#define GLYPH_WIDTH 8 +#define GLYPH_HEIGHT 19 + +#define EFI_HII_FONT 1 +#define EFI_HII_STRING 2 +#define EFI_HII_IFR 3 +#define EFI_HII_KEYBOARD 4 +#define EFI_HII_HANDLES 5 +#define EFI_HII_VARIABLE 6 +#define EFI_HII_DEVICE_PATH 7 + + +// References to string tokens must use this macro to enable scanning for +// token usages. +// +#define STRING_TOKEN(t) t + +// +// The following types are currently defined: +// +typedef UINT16 EFI_FORM_ID; +typedef UINT16 EFI_FORM_LABEL; + +#pragma pack(1) + +typedef struct { + UINT32 Length; + UINT16 Type; +} EFI_HII_PACK_HEADER; + +// +// A form list consists of a large variety of structure +// possibilities so to represent the binary blob of data +// associated with a package of forms, we will assume a +// pointer to a self-describing data buffer. +// +typedef struct { + EFI_HII_PACK_HEADER Header; +} EFI_HII_IFR_PACK; + +typedef struct { + EFI_HII_PACK_HEADER Header; // Must be filled in + EFI_HANDLE ImageHandle; // Must be filled in + EFI_HANDLE DeviceHandle; // Optional + EFI_HANDLE ControllerHandle; // Optional + EFI_HANDLE CallbackHandle; // Optional + EFI_HANDLE COBExportHandle; // Optional +} EFI_HII_HANDLE_PACK; + +// +// ******************************************************** +// EFI_VARIABLE_CONTENTS +// ******************************************************** +// +typedef struct { + EFI_HII_PACK_HEADER Header; + EFI_GUID VariableGuid; + UINT32 VariableNameLength; + UINT16 VariableId; + // + // CHAR16 VariableName[]; //Null-terminated + // +} EFI_HII_VARIABLE_PACK; + +// +// ******************************************************** +// EFI_DEVICE_PATH_PACK +// ******************************************************** +// +typedef struct { + EFI_HII_PACK_HEADER Header; + // + // EFI_DEVICE_PATH DevicePath[]; + // +} EFI_HII_DEVICE_PATH_PACK; + +// +// ******************************************************** +// EFI_HII_DATA_TABLE +// ******************************************************** +// +typedef struct { + EFI_HII_HANDLE HiiHandle; + EFI_GUID PackageGuid; + UINT32 DataTableSize; + UINT32 IfrDataOffset; + UINT32 StringDataOffset; + UINT32 VariableDataOffset; + UINT32 DevicePathOffset; + UINT32 NumberOfVariableData; + UINT32 NumberOfLanguages; + // + // EFI_HII_DEVICE_PATH_PACK DevicePath[]; + // EFI_HII_VARIABLE_PACK VariableData[]; + // EFI_HII_IFR_PACK IfrData; + // EFI_HII_STRING_PACK StringData[]; + // +} EFI_HII_DATA_TABLE; + +// +// ******************************************************** +// EFI_HII_EXPORT_TABLE +// ******************************************************** +// +typedef struct { + UINT32 NumberOfHiiDataTables; + EFI_GUID Revision; + // + // EFI_HII_DATA_TABLE HiiDataTable[]; + // +} EFI_HII_EXPORT_TABLE; + +typedef struct { + BOOLEAN FormSetUpdate; // If TRUE, next variable is significant + EFI_PHYSICAL_ADDRESS FormCallbackHandle; // If not 0, will update Formset with this info + BOOLEAN FormUpdate; // If TRUE, next variable is significant + UINT16 FormValue; // specify which form is to be updated if FormUpdate value is TRUE. + STRING_REF FormTitle; // If not 0, will update Form with this info + UINT16 DataCount; // The number of Data entries in this structure + UINT8 *Data; // An array of 1+ op-codes, specified by DataCount +} EFI_HII_UPDATE_DATA; + +// +// String attributes +// +#define LANG_RIGHT_TO_LEFT 0x00000001 + +// +// A string package is used to localize strings to a particular +// language. The package is associated with a particular driver +// or set of drivers. Tools are used to associate tokens with +// string references in forms and in programs. These tokens are +// language agnostic. When paired with a language pack (directly +// or indirectly), the string token resolves into an actual +// UNICODE string. The NumStringPointers determines how many +// StringPointers (offset values) there are as well as the total +// number of Strings that are defined. +// +typedef struct { + EFI_HII_PACK_HEADER Header; + RELOFST LanguageNameString; + RELOFST PrintableLanguageName; + UINT32 NumStringPointers; + UINT32 Attributes; + // + // RELOFST StringPointers[]; + // EFI_STRING Strings[]; + // +} EFI_HII_STRING_PACK; + +// +// Glyph Attributes +// +#define EFI_GLYPH_NON_SPACING 1 +#define EFI_GLYPH_WIDE 2 + +typedef struct { + CHAR16 UnicodeWeight; + UINT8 Attributes; + UINT8 GlyphCol1[GLYPH_HEIGHT]; +} EFI_NARROW_GLYPH; + +typedef struct { + CHAR16 UnicodeWeight; + UINT8 Attributes; + UINT8 GlyphCol1[GLYPH_HEIGHT]; + UINT8 GlyphCol2[GLYPH_HEIGHT]; + UINT8 Pad[3]; +} EFI_WIDE_GLYPH; + +// +// A font list consists of a font header followed by a series +// of glyph structures. Note that fonts are not language specific. +// +typedef struct { + EFI_HII_PACK_HEADER Header; + UINT16 NumberOfNarrowGlyphs; + UINT16 NumberOfWideGlyphs; +} EFI_HII_FONT_PACK; + +// +// The IfrData in the EFI_HII_IFR_PACK structure definition +// is variable length, and not really part of the header. To +// simplify from code the size of the header, define an +// identical structure that does not include the IfrData field. +// Then use sizeof() this new structure to determine the +// actual size of the header. +// +typedef struct { + EFI_HII_PACK_HEADER Header; +} EFI_HII_IFR_PACK_HEADER; + +// +// pedef EFI_HII_PACK_HEADER EFI_HII_IFR_PACK_HEADER; +// +typedef enum { + EfiKeyLCtrl, + EfiKeyA0, + EfiKeyLAlt, + EfiKeySpaceBar, + EfiKeyA2, + EfiKeyA3, + EfiKeyA4, + EfiKeyRCtrl, + EfiKeyLeftArrow, + EfiKeyDownArrow, + EfiKeyRightArrow, + EfiKeyZero, + EfiKeyPeriod, + EfiKeyEnter, + EfiKeyLShift, + EfiKeyB0, + EfiKeyB1, + EfiKeyB2, + EfiKeyB3, + EfiKeyB4, + EfiKeyB5, + EfiKeyB6, + EfiKeyB7, + EfiKeyB8, + EfiKeyB9, + EfiKeyB10, + EfiKeyRshift, + EfiKeyUpArrow, + EfiKeyOne, + EfiKeyTwo, + EfiKeyThree, + EfiKeyCapsLock, + EfiKeyC1, + EfiKeyC2, + EfiKeyC3, + EfiKeyC4, + EfiKeyC5, + EfiKeyC6, + EfiKeyC7, + EfiKeyC8, + EfiKeyC9, + EfiKeyC10, + EfiKeyC11, + EfiKeyC12, + EfiKeyFour, + EfiKeyFive, + EfiKeySix, + EfiKeyPlus, + EfiKeyTab, + EfiKeyD1, + EfiKeyD2, + EfiKeyD3, + EfiKeyD4, + EfiKeyD5, + EfiKeyD6, + EfiKeyD7, + EfiKeyD8, + EfiKeyD9, + EfiKeyD10, + EfiKeyD11, + EfiKeyD12, + EfiKeyD13, + EfiKeyDel, + EfiKeyEnd, + EfiKeyPgDn, + EfiKeySeven, + EfiKeyEight, + EfiKeyNine, + EfiKeyE0, + EfiKeyE1, + EfiKeyE2, + EfiKeyE3, + EfiKeyE4, + EfiKeyE5, + EfiKeyE6, + EfiKeyE7, + EfiKeyE8, + EfiKeyE9, + EfiKeyE10, + EfiKeyE11, + EfiKeyE12, + EfiKeyBackSpace, + EfiKeyIns, + EfiKeyHome, + EfiKeyPgUp, + EfiKeyNLck, + EfiKeySlash, + EfiKeyAsterisk, + EfiKeyMinus, + EfiKeyEsc, + EfiKeyF1, + EfiKeyF2, + EfiKeyF3, + EfiKeyF4, + EfiKeyF5, + EfiKeyF6, + EfiKeyF7, + EfiKeyF8, + EfiKeyF9, + EfiKeyF10, + EfiKeyF11, + EfiKeyF12, + EfiKeyPrint, + EfiKeySLck, + EfiKeyPause +} EFI_KEY; + +typedef struct { + EFI_KEY Key; + CHAR16 Unicode; + CHAR16 ShiftedUnicode; + CHAR16 AltGrUnicode; + CHAR16 ShiftedAltGrUnicode; + UINT16 Modifier; +} EFI_KEY_DESCRIPTOR; + +// +// This structure allows a sparse set of keys to be redefined +// or a complete redefinition of the keyboard layout. Most +// keyboards have a lot of commonality in their layouts, therefore +// only defining those keys that need to change from the default +// minimizes the passed in information. +// +// Additionally, when an update occurs, the active keyboard layout +// will be switched to the newly updated keyboard layout. This +// allows for situations that when a keyboard layout driver is +// loaded as part of system initialization, the system will default +// the keyboard behavior to the new layout. +// +// Each call to update the keyboard mapping should contain the +// complete set of key descriptors to be updated, since every +// call to the HII which contains an EFI_HII_KEYBOARD_PACK will +// wipe the previous set of overrides. A call to +// +typedef struct { + EFI_HII_PACK_HEADER Header; + EFI_KEY_DESCRIPTOR *Descriptor; + UINT8 DescriptorCount; +} EFI_HII_KEYBOARD_PACK; + +// +// The EFI_HII_PACKAGES can contain different types of packages just +// after the structure as inline data. +// +typedef struct { + UINTN NumberOfPackages; + EFI_GUID *GuidId; + // + // EFI_HII_HANDLE_PACK *HandlePack; // Only one pack. + // EFI_HII_IFR_PACK *IfrPack; // Only one pack. + // EFI_HII_FONT_PACK *FontPack[]; // Multiple packs ok + // EFI_HII_STRING_PACK *StringPack[]; // Multiple packs ok + // EFI_HII_KEYBOARD_PACK *KeyboardPack[]; // Multiple packs ok + // +} EFI_HII_PACKAGES; + +typedef struct _EFI_HII_VARIABLE_PACK_LIST { + struct _EFI_HII_VARIABLE_PACK_LIST *NextVariablePack; + EFI_HII_VARIABLE_PACK *VariablePack; +} EFI_HII_VARIABLE_PACK_LIST; + +#pragma pack() + +/** + Registers the various packs that are passed in via the Packages parameter. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Packages A pointer to an EFI_HII_PACKAGES package instance. + @param Handle A pointer to the EFI_HII_HANDLE instance. + + @retval EFI_SUCCESS Data was extracted from Packages, the database + was updated with the data, and Handle returned successfully. + @retval EFI_INVALID_PARAMETER The content of Packages was invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_NEW_PACK) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_PACKAGES *Packages, + OUT EFI_HII_HANDLE *Handle + ); + +/** + Removes a package from the HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle The handle that was registered to the data that is requested + for removal. + + @retval EFI_SUCCESS The data associated with the Handle was removed + from the HII database. + @retval EFI_INVALID_PARAMETER The Handle was not valid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_REMOVE_PACK) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle + ); + +/** + Determines the handles that are currently active in the database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param HandleBufferLength On input, a pointer to the length of the handle + buffer. On output, the length of the handle buffer that is required + for the handles found. + @param Handle An array of EFI_HII_HANDLE instances returned. + + @retval EFI_SUCCESS Handle was updated successfully. + @retval EFI_BUFFER_TOO_SMALL The HandleBufferLength parameter indicates + that Handle is too small to support the number of handles. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_FIND_HANDLES) ( + IN EFI_HII_PROTOCOL *This, + IN OUT UINT16 *HandleBufferLength, + OUT EFI_HII_HANDLE *Handle + ); + +/** + Exports the contents of the database into a buffer. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle An EFI_HII_HANDLE that corresponds to the desired + handle to export. If the value is 0, the entire database will be exported. + In either case, the data will be exported in a format described by the + structure definition of EFI_HII_EXPORT_TABLE. + @param BufferSize + On input, a pointer to the length of the buffer. On output, the length + of the buffer that is required for the export data. + @param Buffer A pointer to a buffer that will contain the results of the export function. + + @retval EFI_SUCCESS The buffer was successfully filled with BufferSize amount of data. + @retval EFI_BUFFER_TOO_SMALL The value in BufferSize was too small to contain the export data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_EXPORT) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +/** + Remove any new strings that were added after the initial string export + for this handle. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle The handle on which the string resides. + + @retval EFI_SUCCESS Remove strings from the handle successfully. + @retval EFI_INVALID_PARAMETER The Handle was unknown. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_RESET_STRINGS) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle + ); + +/** + Tests if all of the characters in a string have corresponding font characters. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param StringToTest A pointer to a Unicode string. + @param FirstMissing A pointer to an index into the string. On input, + the index of the first character in the StringToTest to examine. On exit, + the index of the first character encountered for which a glyph is unavailable. + If all glyphs in the string are available, the index is the index of the + terminator of the string. + @param GlyphBufferSize A pointer to a value. On output, if the function + returns EFI_SUCCESS, it contains the amount of memory that is required to + store the string's glyph equivalent. + + @retval EFI_SUCCESS All glyphs are available. Note that an empty string + always returns this value. + @retval EFI_NOT_FOUND A glyph was not found for a character. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_TEST_STRING) ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *StringToTest, + IN OUT UINT32 *FirstMissing, + OUT UINT32 *GlyphBufferSize + ); + +/** + Translates a Unicode character into the corresponding font glyph. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Source A pointer to a Unicode string. + @param Index On input, the offset into the string from which to fetch + the character.On successful completion, the index is updated to the first + character past the character(s) making up the just extracted glyph. + @param GlyphBuffer Pointer to an array where the glyphs corresponding + to the characters in the source may be stored. GlyphBuffer is assumed + to be wide enough to accept a wide glyph character. + @param BitWidth If EFI_SUCCESS was returned, the UINT16 pointed to by + this value is filled with the length of the glyph in pixels. It is unchanged + if the call was unsuccessful. + @param InternalStatus The cell pointed to by this parameter must be + initialized to zero prior to invoking the call the first time for any string. + + @retval EFI_SUCCESS It worked. + @retval EFI_NOT_FOUND A glyph for a character was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_GLYPH) ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Source, + IN OUT UINT16 *Index, + OUT UINT8 **GlyphBuffer, + OUT UINT16 *BitWidth, + IN OUT UINT32 *InternalStatus + ); + +/** + Translates a glyph into the format required for input to the Universal + Graphics Adapter (UGA) Block Transfer (BLT) routines. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param GlyphBuffer A pointer to the buffer that contains glyph data. + @param Foreground The foreground setting requested to be used for the + generated BltBuffer data. + @param Background The background setting requested to be used for the + generated BltBuffer data. + @param Count The entry in the BltBuffer upon which to act. + @param Width The width in bits of the glyph being converted. + @param Height The height in bits of the glyph being converted + @param BltBuffer A pointer to the buffer that contains the data that is + ready to be used by the UGA BLT routines. + + @retval EFI_SUCCESS It worked. + @retval EFI_NOT_FOUND A glyph for a character was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GLYPH_TO_BLT) ( + IN EFI_HII_PROTOCOL *This, + IN UINT8 *GlyphBuffer, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background, + IN UINTN Count, + IN UINTN Width, + IN UINTN Height, + IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer + ); + +/** + Allows a new string to be added to an already existing string package. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Pointer to a NULL-terminated string containing a single ISO 639-2 + language identifier, indicating the language in which the string is translated. + @param Handle The handle of the language pack to which the string is to be added. + @param Reference The identifier of the string to be added. If the reference + value is zero, then the string will be assigned a new identifier on that + handle for the language specified. Otherwise, the string will be updated + with the NewString Value. + @param NewString The string to be added. + + @retval EFI_SUCCESS The string was effectively registered. + @retval EFI_INVALID_PARAMETER The Handle was unknown. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_NEW_STRING) ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Language, + IN EFI_HII_HANDLE Handle, + IN OUT STRING_REF *Reference, + IN CHAR16 *NewString + ); + +/** + Allows a program to determine the primary languages that are supported + on a given handle. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle The handle on which the strings reside. + @param LanguageString A string allocated by GetPrimaryLanguages() that + contains a list of all primary languages registered on the handle. + + @retval EFI_SUCCESS LanguageString was correctly returned. + @retval EFI_INVALID_PARAMETER The Handle was unknown. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_PRI_LANGUAGES) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + OUT EFI_STRING *LanguageString + ); + +/** + Allows a program to determine which secondary languages are supported + on a given handle for a given primary language. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle The handle on which the strings reside. + @param PrimaryLanguage Pointer to a NULL-terminated string containing a single + ISO 639-2 language identifier, indicating the primary language. + @param LanguageString A string allocated by GetSecondaryLanguages() + containing a list of all secondary languages registered on the handle. + + @retval EFI_SUCCESS LanguageString was correctly returned. + @retval EFI_INVALID_PARAMETER The Handle was unknown. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_SEC_LANGUAGES) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN CHAR16 *PrimaryLanguage, + OUT EFI_STRING *LanguageString + ); + +/** + Extracts a string from a package already registered with the EFI HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle The handle on which the string resides. + @param Token The string token assigned to the string. + @param Raw If TRUE, the string is returned unedited in the internal + storage format described above. If false, the string returned is edited + by replacing with and by removing special characters such + as the prefix. + @param LanguageString Pointer to a NULL-terminated string containing a + single ISO 639-2 language identifier, indicating the language to print. + If the LanguageString is empty (starts with a NULL), the default system + language will be used to determine the language. + @param BufferLength Length of the StringBuffer. + @param StringBuffer The buffer designed to receive the characters in the string. + + @retval EFI_SUCCESS StringBuffer is filled with a NULL-terminated string. + @retval EFI_INVALID_PARAMETER The handle or string token is unknown. + @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough to + allow the entire string to be stored. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_STRING) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN BOOLEAN Raw, + IN CHAR16 *LanguageString, + IN OUT UINTN *BufferLength, + OUT EFI_STRING StringBuffer + ); + +/** + Allows a program to extract a part of a string of not more than a given width. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle The handle on which the string resides. + @param Token The string token assigned to the string. + @param Index On input, the offset into the string where the line is to start. + On output, the index is updated to point to beyond the last character returned + in the call. + @param LineWidth The maximum width of the line in units of narrow glyphs. + @param LanguageString Pointer to a NULL-terminated string containing a + single ISO 639-2 language identifier, indicating the language to print. + @param BufferLength Pointer to the length of the StringBuffer. + @param StringBuffer The buffer designed to receive the characters in the string. + + @retval EFI_SUCCESS StringBuffer filled with characters that will fit on the line. + @retval EFI_NOT_FOUND The font glyph for at least one of the characters in + the string is not in the font database. + @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough + to allow the entire string to be stored. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_LINE) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN OUT UINT16 *Index, + IN UINT16 LineWidth, + IN CHAR16 *LanguageString, + IN OUT UINT16 *BufferLength, + OUT EFI_STRING StringBuffer + ); + +/** + Allows a program to extract a form or form package that has previously + been registered with the HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle Handle on which the form resides. + @param FormId The ID of the form to return. If the ID is zero, + the entire form package is returned. + @param BufferLength On input, the length of the Buffer. On output, + the length of the returned buffer, + @param Buffer The buffer designed to receive the form(s). + + @retval EFI_SUCCESS Buffer filled with the requested forms. BufferLength + was updated. + @retval EFI_INVALID_PARAMETER The handle is unknown. + @retval EFI_NOT_FOUND A form on the requested handle cannot be found with + the requested FormId. + @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough + to allow the form to be stored. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_FORMS) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_ID FormId, + IN OUT UINTN *BufferLength, + OUT UINT8 *Buffer + ); + +/** + Extracts the defaults that are associated with a given handle in the HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle The HII handle from which will have default data retrieved. + @param DefaultMask The mask used to specify some type of default override when extracting + the default image data. + @param VariablePackList A indirect pointer to the first entry of a link list with + type EFI_HII_VARIABLE_PACK_LIST. + + @retval EFI_SUCCESS The VariablePackList was populated with the appropriate + default setting data. + @retval EFI_NOT_FOUND The IFR does not have any explicit or default map(s). + @retval EFI_INVALID_PARAMETER The HII database entry associated with Handle + contain invalid data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_DEFAULT_IMAGE) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN UINTN DefaultMask, + OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList + ); + +/** + Allows the caller to update a form or form package that has previously been + registered with the EFI HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle Handle of the package where the form to be updated resides. + @param Label The label inside the form package where the update is to take place. + @param AddData If TRUE, adding data at a given Label; otherwise, + if FALSE, removing data at a given Label. + @param Data The buffer containing the new tags to insert after the Label + + @retval EFI_SUCCESS The form was updated with the new tags. + @retval EFI_INVALID_PARAMETER The buffer for the buffer length does not + contain an integral number of tags. + @retval EFI_NOT_FOUND The Handle, Label, or FormId was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_UPDATE_FORM) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_LABEL Label, + IN BOOLEAN AddData, + IN EFI_HII_UPDATE_DATA *Data + ); + +/** + Retrieves the current keyboard layout. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param DescriptorCount A pointer to the number of Descriptor entries being + described in the keyboard layout being retrieved. + @param Descriptor A pointer to a buffer containing an array of EFI_KEY_DESCRIPTOR + entries. Each entry will reflect the definition of a specific physical key. + + @retval EFI_SUCCESS The keyboard layout was retrieved successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_KEYBOARD_LAYOUT) ( + IN EFI_HII_PROTOCOL *This, + OUT UINT16 *DescriptorCount, + OUT EFI_KEY_DESCRIPTOR *Descriptor + ); + +/** + @par Protocol Description: + The HII Protocol manages the HII database, which is a repository for data + having to do with fonts, strings, forms, keyboards, and other future human + interface items. + + @param NewPack + Extracts the various packs from a package list. + + @param RemovePack + Removes a package from the HII database. + + @param FindHandles + Determines the handles that are currently active in the database. + + @param ExportDatabase + Export the entire contents of the database to a buffer. + + @param TestString + Tests if all of the characters in a string have corresponding font characters. + + @param GetGlyph + Translates a Unicode character into the corresponding font glyph. + + @param GlyphToBlt + Converts a glyph value into a format that is ready for a UGA BLT command. + + @param NewString + Allows a new string to be added to an already existing string package. + + @param GetPrimaryLanguages + Allows a program to determine the primary languages that are supported + on a given handle. + + @param GetSecondaryLanguages + Allows a program to determine which secondary languages are supported + on a given handle for a given primary language. + + @param GetString + Extracts a string from a package that is already registered with the + EFI HII database. + + @param ResetString + Remove any new strings that were added after the initial string export + for this handle. + + @param GetLine + Allows a program to extract a part of a string of not more than a given width. + + @param GetForms + Allows a program to extract a form or form package that has been previously registered. + + @param GetDefaultImage + Allows a program to extract the nonvolatile image that represents the default storage image. + + @param UpdateForm + Allows a program to update a previously registered form. + + @param GetKeyboardLayout + Allows a program to extract the current keyboard layout. + +**/ +struct _EFI_HII_PROTOCOL { + EFI_HII_NEW_PACK NewPack; + EFI_HII_REMOVE_PACK RemovePack; + EFI_HII_FIND_HANDLES FindHandles; + EFI_HII_EXPORT ExportDatabase; + + EFI_HII_TEST_STRING TestString; + EFI_HII_GET_GLYPH GetGlyph; + EFI_HII_GLYPH_TO_BLT GlyphToBlt; + + EFI_HII_NEW_STRING NewString; + EFI_HII_GET_PRI_LANGUAGES GetPrimaryLanguages; + EFI_HII_GET_SEC_LANGUAGES GetSecondaryLanguages; + EFI_HII_GET_STRING GetString; + EFI_HII_RESET_STRINGS ResetStrings; + EFI_HII_GET_LINE GetLine; + EFI_HII_GET_FORMS GetForms; + EFI_HII_GET_DEFAULT_IMAGE GetDefaultImage; + EFI_HII_UPDATE_FORM UpdateForm; + + EFI_HII_GET_KEYBOARD_LAYOUT GetKeyboardLayout; +}; + +extern EFI_GUID gEfiHiiProtocolGuid; + +#endif diff --git a/MdeModulePkg/Core/DxeIplPeim/CommonHeader.h b/MdeModulePkg/Core/DxeIplPeim/CommonHeader.h new file mode 100644 index 0000000000..2240f6ddeb --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/CommonHeader.h @@ -0,0 +1,56 @@ +/**@file + Common header file shared by all source files. + + This file includes package header files, library classes and protocol, PPI & GUID definitions. + + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + + +// +// The package level header files this module uses +// +#include +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.dxs b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.dxs new file mode 100644 index 0000000000..015c180790 --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.dxs @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DxeIpl.dxs + +Abstract: + + Dependency expression file for DXE Initial Program Loader PEIM. + +--*/ + +#include + +DEPENDENCY_START + EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI_GUID +DEPENDENCY_END + + diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h new file mode 100644 index 0000000000..5315b8b9dc --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h @@ -0,0 +1,117 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DxeIpl.h + +Abstract: + +--*/ + +#ifndef __PEI_DXEIPL_H__ +#define __PEI_DXEIPL_H__ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#define STACK_SIZE 0x20000 +#define BSP_STORE_SIZE 0x4000 + +#define GET_OCCUPIED_SIZE(ActualSize, Alignment) ((ActualSize + (Alignment - 1)) & ~(Alignment - 1)) + +extern BOOLEAN gInMemory; + +EFI_STATUS +PeiFindFile ( + IN UINT8 Type, + IN UINT16 SectionType, + OUT EFI_GUID *FileName, + OUT VOID **Pe32Data + ) +; + +EFI_STATUS +PeiLoadFile ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader, + IN VOID *Pe32Data, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +; + + +EFI_STATUS +GetImageReadFunction ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +; + +EFI_STATUS +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +; + +EFI_STATUS +EFIAPI +DxeIplLoadFile ( + IN EFI_PEI_FV_FILE_LOADER_PPI *This, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ); + +EFI_STATUS +ShadowDxeIpl ( + IN EFI_FFS_FILE_HEADER *DxeIpl, + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader + ); + +EFI_STATUS +EFIAPI +DxeLoadCore ( + IN EFI_DXE_IPL_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_HOB_POINTERS HobList + ); + +VOID +HandOffToDxeCore ( + IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint, + IN EFI_PEI_HOB_POINTERS HobList, + IN EFI_PEI_PPI_DESCRIPTOR *EndOfPeiSignal + ); + +EFI_STATUS +PeiProcessFile ( + IN UINT16 SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + OUT VOID **Pe32Data, + IN EFI_PEI_HOB_POINTERS *OrigHob + ); + +EFI_STATUS +EFIAPI +PeimInitializeDxeIpl ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ); + + +#endif diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf new file mode 100644 index 0000000000..96e578f0d0 --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf @@ -0,0 +1,171 @@ +#/** @file +# Component description file for DxeIpl module +# +# The responsibility of this module is to load the DXE Core from a Firmware Volume. This implementation i used to load a 32-bit DXE Core. +# Copyright (c) 2006 - 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeIpl + FILE_GUID = 86D70125-BAA3-4296-A62F-602BEBBB9081 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + ENTRY_POINT = PeimInitializeDxeIpl + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ + +[Sources.common] + DxeIpl.h + DxeLoad.c + CommonHeader.h + +[Sources.Ia32] + Ia32/VirtualMemory.h + Ia32/VirtualMemory.c + Ia32/DxeLoadFunc.c + Ia32/ImageRead.c + +[Sources.X64] + X64/DxeLoadFunc.c + Ia32/ImageRead.c + +[Sources.IPF] + Ipf/DxeLoadFunc.c + Ipf/ImageRead.c + +[Sources.EBC] + X64/DxeLoadFunc.c + Ia32/ImageRead.c + + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + + +################################################################################ +# +# Library Class Section - list of Library Classes that are required for +# this module. +# +################################################################################ + +[LibraryClasses] + PeCoffLib + PcdLib + MemoryAllocationLib + BaseMemoryLib + PeiServicesTablePointerLib + CustomDecompressLib + TianoDecompressLib + UefiDecompressLib + EdkPeCoffLoaderLib + CacheMaintenanceLib + ReportStatusCodeLib + PeiServicesLib + HobLib + BaseLib + PeimEntryPoint + DebugLib + + +################################################################################ +# +# Guid C Name Section - list of Guids that this module uses or produces. +# +################################################################################ + + +################################################################################ +# +# Protocol C Name Section - list of Protocol and Protocol Notify C Names +# that this module uses or produces. +# +################################################################################ + +[Protocols] + gEfiCustomizedDecompressProtocolGuid # PROTOCOL SOMETIMES_PRODUCED + gEfiTianoDecompressProtocolGuid # PROTOCOL SOMETIMES_PRODUCED + gEfiDecompressProtocolGuid # PROTOCOL SOMETIMES_PRODUCED + + +################################################################################ +# +# PPI C Name Section - list of PPI and PPI Notify C Names that this module +# uses or produces. +# +################################################################################ + +[Ppis] + gEfiPeiSecurityPpiGuid # PPI SOMETIMES_CONSUMED + gEfiPeiSectionExtractionPpiGuid # PPI SOMETIMES_CONSUMED + gEfiPeiS3ResumePpiGuid # PPI SOMETIMES_CONSUMED + gEfiPeiRecoveryModulePpiGuid # PPI SOMETIMES_CONSUMED + gEfiEndOfPeiSignalPpiGuid # PPI SOMETIMES_PRODUCED + gEfiPeiFvFileLoaderPpiGuid # PPI SOMETIMES_PRODUCED + gEfiDxeIplPpiGuid # PPI SOMETIMES_PRODUCED + gEfiPeiPeCoffLoaderGuid + + +################################################################################ +# +# Pcd FEATURE_FLAG - list of PCDs that this module is coded for. +# +################################################################################ + +[PcdsFeatureFlag.common] + PcdDxeIplSupportCustomDecompress|gEfiEdkModulePkgTokenSpaceGuid + PcdDxeIplSupportTianoDecompress|gEfiEdkModulePkgTokenSpaceGuid + PcdDxeIplSupportEfiDecompress|gEfiEdkModulePkgTokenSpaceGuid + PcdDxeIplBuildShareCodeHobs|gEfiEdkModulePkgTokenSpaceGuid + +[PcdsFeatureFlag.IA32] + PcdDxeIplSwitchToLongMode|gEfiMdeModulePkgTokenSpaceGuid + + +################################################################################ +# +# Dependency Expression Section - list of Dependency expressions that are required for +# this module. +# +################################################################################ + +[Depex] + gEfiPeiMemoryDiscoveredPpiGuid + diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.msa b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.msa new file mode 100644 index 0000000000..c552966169 --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.msa @@ -0,0 +1,168 @@ + + + + DxeIpl + PEIM + 86D70125-BAA3-4296-A62F-602BEBBB9081 + 1.0 + Component description file for DxeIpl module + The responsibility of this module is to load the DXE Core from a Firmware Volume. This implementation i used to load a 32-bit DXE Core. + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + DxeIpl + + + + DebugLib + + + PeimEntryPoint + + + BaseLib + + + HobLib + + + PeiServicesLib + + + ReportStatusCodeLib + + + CacheMaintenanceLib + + + EdkPeCoffLoaderLib + + + UefiDecompressLib + + + TianoDecompressLib + + + CustomDecompressLib + + + PeiServicesTablePointerLib + + + BaseMemoryLib + + + MemoryAllocationLib + + + PcdLib + + + PeCoffLib + + + + DxeLoad.c + DxeIpl.h + DxeIpl.dxs + Ia32/ImageRead.c + Ia32/DxeLoadFunc.c + Ia32/VirtualMemory.c + Ia32/VirtualMemory.h + X64/DxeLoadFunc.c + Ipf/ImageRead.c + Ipf/DxeLoadFunc.c + + + + + + + + gEfiDecompressProtocolGuid + + + gEfiTianoDecompressProtocolGuid + + + gEfiCustomizedDecompressProtocolGuid + + + + + gEfiDxeIplPpiGuid + + + gEfiPeiFvFileLoaderPpiGuid + + + gEfiEndOfPeiSignalPpiGuid + + + gEfiPeiRecoveryModulePpiGuid + + + gEfiPeiS3ResumePpiGuid + + + gEfiPeiSectionExtractionPpiGuid + + + gEfiPeiSecurityPpiGuid + + + + + gEfiPeiPeCoffLoaderGuid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + PeimInitializeDxeIpl + + + + + PcdDxeIplSwitchToLongMode + gEfiEdkModulePkgTokenSpaceGuid + TRUE + If this feature is enabled, then the DXE IPL will load a 64-bit DxeCore. + + + PcdDxeIplBuildShareCodeHobs + gEfiEdkModulePkgTokenSpaceGuid + FALSE + If this feature is enabled, DXE IPL will build a series of HOBs to share code with DXE Core. + + + PcdDxeIplSupportEfiDecompress + gEfiEdkModulePkgTokenSpaceGuid + TRUE + If this feature is enabled, then the DXE IPL must support decompressing files compressed with the EFI Compression algorithm + + + PcdDxeIplSupportTianoDecompress + gEfiEdkModulePkgTokenSpaceGuid + TRUE + If this feature is enabled, then the DXE IPL must support decompressing files compressed with the Tiano Compression algorithm + + + PcdDxeIplSupportCustomDecompress + gEfiEdkModulePkgTokenSpaceGuid + TRUE + If this feature is enabled, then the DXE IPL must support decompressing files compressed with the Custom Compression algorithm + + + \ No newline at end of file diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c new file mode 100644 index 0000000000..eec1d864da --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c @@ -0,0 +1,980 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DxeLoad.c + +Abstract: + + Last PEIM. + Responsibility of this module is to load the DXE Core from a Firmware Volume. + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "DxeIpl.h" + +// porting note remove later +#include "Common/DecompressLibraryHob.h" +#include "FrameworkPei.h" +// end of remove later + +BOOLEAN gInMemory = FALSE; + +// +// Module Globals used in the DXE to PEI handoff +// These must be module globals, so the stack can be switched +// +static EFI_DXE_IPL_PPI mDxeIplPpi = { + DxeLoadCore +}; + +static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi = { + DxeIplLoadFile +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiList[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiPeiFvFileLoaderPpiGuid, + &mLoadFilePpi + }, + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiDxeIplPpiGuid, + &mDxeIplPpi + } +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiEndOfPeiSignalPpiGuid, + NULL +}; + +GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gEfiDecompress = { + UefiDecompressGetInfo, + UefiDecompress +}; + +GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gCustomDecompress = { + CustomDecompressGetInfo, + CustomDecompress +}; + +EFI_STATUS +EFIAPI +PeimInitializeDxeIpl ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Initializes the Dxe Ipl PPI + +Arguments: + + FfsHeader - Pointer to FFS file header + PeiServices - General purpose services available to every PEIM. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + EFI_BOOT_MODE BootMode; + + Status = PeiServicesGetBootMode (&BootMode); + ASSERT_EFI_ERROR (Status); + + if (!gInMemory && (BootMode != BOOT_ON_S3_RESUME)) { + // + // The DxeIpl has not yet been shadowed + // + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + + // + // Shadow DxeIpl and then re-run its entry point + // + Status = ShadowDxeIpl (FfsHeader, PeiEfiPeiPeCoffLoader); + } else { + // + // Install FvFileLoader and DxeIpl PPIs. + // + Status = PeiServicesInstallPpi (mPpiList); + ASSERT_EFI_ERROR(Status); + } + + return Status; +} + +EFI_STATUS +EFIAPI +DxeLoadCore ( + IN EFI_DXE_IPL_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_HOB_POINTERS HobList + ) +/*++ + +Routine Description: + + Main entry point to last PEIM + +Arguments: + This - Entry point for DXE IPL PPI + PeiServices - General purpose services available to every PEIM. + HobList - Address to the Pei HOB list + +Returns: + + EFI_SUCCESS - DEX core was successfully loaded. + EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core. + +--*/ +{ + EFI_STATUS Status; + EFI_GUID DxeCoreFileName; + EFI_GUID FirmwareFileName; + VOID *Pe32Data; + VOID *FvImageData; + EFI_PHYSICAL_ADDRESS DxeCoreAddress; + UINT64 DxeCoreSize; + EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + EFI_BOOT_MODE BootMode; + EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery; + EFI_PEI_S3_RESUME_PPI *S3Resume; + +// PERF_START (PeiServices, L"DxeIpl", NULL, 0); + + // + // if in S3 Resume, restore configure + // + Status = PeiServicesGetBootMode (&BootMode); + ASSERT_EFI_ERROR(Status); + + if (BootMode == BOOT_ON_S3_RESUME) { + Status = PeiServicesLocatePpi ( + &gEfiPeiS3ResumePpiGuid, + 0, + NULL, + (VOID **)&S3Resume + ); + ASSERT_EFI_ERROR (Status); + + Status = S3Resume->S3RestoreConfig (PeiServices); + ASSERT_EFI_ERROR (Status); + } else if (BootMode == BOOT_IN_RECOVERY_MODE) { + + Status = PeiServicesLocatePpi ( + &gEfiPeiRecoveryModulePpiGuid, + 0, + NULL, + (VOID **)&PeiRecovery + ); + ASSERT_EFI_ERROR (Status); + + Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status)); + CpuDeadLoop (); + } + + // + // Now should have a HOB with the DXE core w/ the old HOB destroyed + // + } + + // + // Install the PEI Protocols that are shared between PEI and DXE + // + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + ASSERT (PeiEfiPeiPeCoffLoader != NULL); + + + // + // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file + // The file found will be processed by PeiProcessFile: It will first be decompressed to + // a normal FV, then a corresponding FV type hob will be built. + // + Status = PeiFindFile ( + EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, + EFI_SECTION_FIRMWARE_VOLUME_IMAGE, + &FirmwareFileName, + &FvImageData + ); + + // + // Find the DXE Core in a Firmware Volume + // + Status = PeiFindFile ( + EFI_FV_FILETYPE_DXE_CORE, + EFI_SECTION_PE32, + &DxeCoreFileName, + &Pe32Data + ); + ASSERT_EFI_ERROR (Status); + + // + // Load the DXE Core from a Firmware Volume + // + Status = PeiLoadFile ( + PeiEfiPeiPeCoffLoader, + Pe32Data, + &DxeCoreAddress, + &DxeCoreSize, + &DxeCoreEntryPoint + ); + ASSERT_EFI_ERROR (Status); + + // + // Add HOB for the DXE Core + // + BuildModuleHob ( + &DxeCoreFileName, + DxeCoreAddress, + DxeCoreSize, + DxeCoreEntryPoint + ); + + // + // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT + ); + + if (FeaturePcdGet (PcdDxeIplBuildShareCodeHobs)) { + if (FeaturePcdGet (PcdDxeIplSupportEfiDecompress)) { + // + // Add HOB for the EFI Decompress Protocol + // + BuildGuidDataHob ( + &gEfiDecompressProtocolGuid, + (VOID *)&gEfiDecompress, + sizeof (gEfiDecompress) + ); + } + if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress)) { + // + // Add HOB for the user customized Decompress Protocol + // + BuildGuidDataHob ( + &gEfiCustomizedDecompressProtocolGuid, + (VOID *)&gCustomDecompress, + sizeof (gCustomDecompress) + ); + } + + // + // Add HOB for the PE/COFF Loader Protocol + // + BuildGuidDataHob ( + &gEfiPeiPeCoffLoaderGuid, + (VOID *)&PeiEfiPeiPeCoffLoader, + sizeof (VOID *) + ); + } + + // + // Transfer control to the DXE Core + // The handoff state is simply a pointer to the HOB list + // + + DEBUG ((EFI_D_INFO, "DXE Core Entry Point 0x%08x\n", (UINTN) DxeCoreEntryPoint)); + HandOffToDxeCore (DxeCoreEntryPoint, HobList, &mPpiSignal); + // + // If we get here, then the DXE Core returned. This is an error + // Dxe Core should not return. + // + ASSERT (FALSE); + CpuDeadLoop (); + + return EFI_OUT_OF_RESOURCES; +} + +EFI_STATUS +PeiFindFile ( + IN UINT8 Type, + IN UINT16 SectionType, + OUT EFI_GUID *FileName, + OUT VOID **Pe32Data + ) +/*++ + +Routine Description: + + Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes + described in the HOB list. Able to search in a compression set in a FFS file. + But only one level of compression is supported, that is, not able to search + in a compression set that is within another compression set. + +Arguments: + + Type - The Type of file to retrieve + + SectionType - The type of section to retrieve from a file + + FileName - The name of the file found in the Firmware Volume + + Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume + +Returns: + + EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to + the PE/COFF image is returned in Pe32Data + + EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FFS_FILE_HEADER *FfsFileHeader; + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS Hob; + + + FwVolHeader = NULL; + FfsFileHeader = NULL; + Status = EFI_SUCCESS; + + // + // For each Firmware Volume, look for a specified type + // of file and break out until no one is found + // + Hob.Raw = GetHobList (); + while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) { + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (Hob.FirmwareVolume->BaseAddress); + // + // Make sure the FV HOB does not get corrupted. + // + ASSERT (FwVolHeader->Signature == EFI_FVH_SIGNATURE); + + Status = PeiServicesFfsFindNextFile ( + Type, + FwVolHeader, + &FfsFileHeader + ); + if (!EFI_ERROR (Status)) { + Status = PeiProcessFile ( + SectionType, + FfsFileHeader, + Pe32Data, + &Hob + ); + CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID)); + // + // Find all Fv type ffs to get all FvImage and add them into FvHob + // + if (!EFI_ERROR (Status) && (Type != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE)) { + return EFI_SUCCESS; + } + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +PeiLoadFile ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader, + IN VOID *Pe32Data, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +/*++ + +Routine Description: + + Loads and relocates a PE/COFF image into memory. + +Arguments: + + PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol + + Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated + + ImageAddress - The base address of the relocated PE/COFF image + + ImageSize - The size of the relocated PE/COFF image + + EntryPoint - The entry point of the relocated PE/COFF image + +Returns: + + EFI_SUCCESS - The file was loaded and relocated + + EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = Pe32Data; + Status = GetImageReadFunction (&ImageContext); + + ASSERT_EFI_ERROR (Status); + + Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Allocate Memory for the image + // + ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize)); + ASSERT (ImageContext.ImageAddress != 0); + + // + // Load the image to our new buffer + // + Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Relocate the image in our new buffer + // + Status = PeiEfiPeiPeCoffLoader->RelocateImage (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Flush the instruction cache so the image data is written before we execute it + // + InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); + + *ImageAddress = ImageContext.ImageAddress; + *ImageSize = ImageContext.ImageSize; + *EntryPoint = ImageContext.EntryPoint; + + return EFI_SUCCESS; +} + +EFI_STATUS +ShadowDxeIpl ( + IN EFI_FFS_FILE_HEADER *DxeIplFileHeader, + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader + ) +/*++ + +Routine Description: + + Shadow the DXE IPL to a different memory location. This occurs after permanent + memory has been discovered. + +Arguments: + + DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver + + PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol + +Returns: + + EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location. + + EFI_ ERROR - The shadow was unsuccessful. + + +--*/ +{ + UINTN SectionLength; + UINTN OccupiedSectionLength; + EFI_PHYSICAL_ADDRESS DxeIplAddress; + UINT64 DxeIplSize; + EFI_PHYSICAL_ADDRESS DxeIplEntryPoint; + EFI_STATUS Status; + EFI_COMMON_SECTION_HEADER *Section; + + Section = (EFI_COMMON_SECTION_HEADER *) (DxeIplFileHeader + 1); + + while ((Section->Type != EFI_SECTION_PE32) && (Section->Type != EFI_SECTION_TE)) { + SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff; + OccupiedSectionLength = GET_OCCUPIED_SIZE (SectionLength, 4); + Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength); + } + // + // Relocate DxeIpl into memory by using loadfile service + // + Status = PeiLoadFile ( + PeiEfiPeiPeCoffLoader, + (VOID *) (Section + 1), + &DxeIplAddress, + &DxeIplSize, + &DxeIplEntryPoint + ); + + if (Status == EFI_SUCCESS) { + // + // Set gInMemory global variable to TRUE to indicate the dxeipl is shadowed. + // + *(BOOLEAN *) ((UINTN) &gInMemory + (UINTN) DxeIplEntryPoint - (UINTN) _ModuleEntryPoint) = TRUE; + Status = ((EFI_PEIM_ENTRY_POINT) (UINTN) DxeIplEntryPoint) ((EFI_PEI_FILE_HANDLE *) DxeIplFileHeader, GetPeiServicesTablePointer()); + } + + return Status; +} + +EFI_STATUS +EFIAPI +DxeIplLoadFile ( + IN EFI_PEI_FV_FILE_LOADER_PPI *This, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +/*++ + +Routine Description: + + Given a pointer to an FFS file containing a PE32 image, get the + information on the PE32 image, and then "load" it so that it + can be executed. + +Arguments: + + This - pointer to our file loader protocol + + FfsHeader - pointer to the FFS file header of the FFS file that + contains the PE32 image we want to load + + ImageAddress - returned address where the PE32 image is loaded + + ImageSize - returned size of the loaded PE32 image + + EntryPoint - entry point to the loaded PE32 image + +Returns: + + EFI_SUCCESS - The FFS file was successfully loaded. + + EFI_ERROR - Unable to load the FFS file. + +--*/ +{ + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + EFI_STATUS Status; + VOID *Pe32Data; + + Pe32Data = NULL; + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + + // + // Preprocess the FFS file to get a pointer to the PE32 information + // in the enclosed PE32 image. + // + Status = PeiProcessFile ( + EFI_SECTION_PE32, + FfsHeader, + &Pe32Data, + NULL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Load the PE image from the FFS file + // + Status = PeiLoadFile ( + PeiEfiPeiPeCoffLoader, + Pe32Data, + ImageAddress, + ImageSize, + EntryPoint + ); + + return Status; +} + +EFI_STATUS +PeiProcessFile ( + IN UINT16 SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + OUT VOID **Pe32Data, + IN EFI_PEI_HOB_POINTERS *OrigHob + ) +/*++ + +Routine Description: + +Arguments: + + SectionType - The type of section in the FFS file to process. + + FfsFileHeader - Pointer to the FFS file to process, looking for the + specified SectionType + + Pe32Data - returned pointer to the start of the PE32 image found + in the FFS file. + +Returns: + + EFI_SUCCESS - found the PE32 section in the FFS file + +--*/ +{ + EFI_STATUS Status; + VOID *SectionData; + DECOMPRESS_LIBRARY *DecompressLibrary; + UINT8 *DstBuffer; + UINT8 *ScratchBuffer; + UINT32 DstBufferSize; + UINT32 ScratchBufferSize; + EFI_COMMON_SECTION_HEADER *CmpSection; + UINTN CmpSectionLength; + UINTN OccupiedCmpSectionLength; + VOID *CmpFileData; + UINTN CmpFileSize; + EFI_COMMON_SECTION_HEADER *Section; + UINTN SectionLength; + UINTN OccupiedSectionLength; + UINT64 FileSize; + UINT32 AuthenticationStatus; + EFI_PEI_SECTION_EXTRACTION_PPI *SectionExtract; + UINT32 BufferSize; + UINT8 *Buffer; + EFI_PEI_SECURITY_PPI *Security; + BOOLEAN StartCrisisRecovery; + EFI_GUID TempGuid; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_COMPRESSION_SECTION *CompressionSection; + + // + // Initialize local variables. + // + DecompressLibrary = NULL; + DstBuffer = NULL; + DstBufferSize = 0; + + Status = PeiServicesFfsFindSectionData ( + EFI_SECTION_COMPRESSION, + FfsFileHeader, + &SectionData + ); + + // + // First process the compression section + // + if (!EFI_ERROR (Status)) { + // + // Yes, there is a compression section, so extract the contents + // Decompress the image here + // + Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER)); + + do { + SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff; + OccupiedSectionLength = GET_OCCUPIED_SIZE (SectionLength, 4); + + // + // Was the DXE Core file encapsulated in a GUID'd section? + // + if (Section->Type == EFI_SECTION_GUID_DEFINED) { + + // + // This following code constitutes the addition of the security model + // to the DXE IPL. + // + // + // Set a default authenticatino state + // + AuthenticationStatus = 0; + + Status = PeiServicesLocatePpi ( + &gEfiPeiSectionExtractionPpiGuid, + 0, + NULL, + (VOID **)&SectionExtract + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Verify Authentication State + // + CopyMem (&TempGuid, Section + 1, sizeof (EFI_GUID)); + + Status = SectionExtract->PeiGetSection ( + GetPeiServicesTablePointer(), + SectionExtract, + (EFI_SECTION_TYPE *) &SectionType, + &TempGuid, + 0, + (VOID **) &Buffer, + &BufferSize, + &AuthenticationStatus + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // If not ask the Security PPI, if exists, for disposition + // + // + Status = PeiServicesLocatePpi ( + &gEfiPeiSecurityPpiGuid, + 0, + NULL, + (VOID **)&Security + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Security->AuthenticationState ( + GetPeiServicesTablePointer(), + (struct _EFI_PEI_SECURITY_PPI *) Security, + AuthenticationStatus, + FfsFileHeader, + &StartCrisisRecovery + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // If there is a security violation, report to caller and have + // the upper-level logic possible engender a crisis recovery + // + if (StartCrisisRecovery) { + return EFI_SECURITY_VIOLATION; + } + } + + if (Section->Type == EFI_SECTION_PE32) { + // + // This is what we want + // + *Pe32Data = (VOID *) (Section + 1); + return EFI_SUCCESS; + } else if (Section->Type == EFI_SECTION_COMPRESSION) { + // + // This is a compression set, expand it + // + CompressionSection = (EFI_COMPRESSION_SECTION *) Section; + + switch (CompressionSection->CompressionType) { + case EFI_STANDARD_COMPRESSION: + // + // Load EFI standard compression. + // + if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress)) { + DecompressLibrary = &gEfiDecompress; + } else { + ASSERT (FALSE); + return EFI_NOT_FOUND; + } + break; + + // porting note the original branch for customized compress is removed, it should be change to use GUID compress + + case EFI_NOT_COMPRESSED: + // + // Allocate destination buffer + // + DstBufferSize = CompressionSection->UncompressedLength; + DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize)); + if (DstBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // stream is not actually compressed, just encapsulated. So just copy it. + // + CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize); + break; + + default: + // + // Don't support other unknown compression type. + // + ASSERT_EFI_ERROR (Status); + return EFI_NOT_FOUND; + } + + if (CompressionSection->CompressionType != EFI_NOT_COMPRESSED) { + // + // For compressed data, decompress them to dstbuffer. + // + Status = DecompressLibrary->GetInfo ( + (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), + (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION), + &DstBufferSize, + &ScratchBufferSize + ); + if (EFI_ERROR (Status)) { + // + // GetInfo failed + // + DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status)); + return EFI_NOT_FOUND; + } + + // + // Allocate scratch buffer + // + ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize)); + if (ScratchBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Allocate destination buffer + // + DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize)); + if (DstBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Call decompress function + // + Status = DecompressLibrary->Decompress ( + (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), + DstBuffer, + ScratchBuffer + ); + if (EFI_ERROR (Status)) { + // + // Decompress failed + // + DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status)); + return EFI_NOT_FOUND; + } + } + + // + // Decompress successfully. + // Loop the decompressed data searching for expected section. + // + CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer; + CmpFileData = (VOID *) DstBuffer; + CmpFileSize = DstBufferSize; + do { + CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff; + if (CmpSection->Type == SectionType) { + // + // This is what we want + // + if (SectionType == EFI_SECTION_PE32) { + *Pe32Data = (VOID *) (CmpSection + 1); + return EFI_SUCCESS; + } else if (SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) { + // + // Firmware Volume Image in this Section + // Skip the section header to get FvHeader + // + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (CmpSection + 1); + + if (FvHeader->Signature == EFI_FVH_SIGNATURE) { + // + // Because FvLength in FvHeader is UINT64 type, + // so FvHeader must meed at least 8 bytes alignment. + // If current FvImage base address doesn't meet its alignment, + // we need to reload this FvImage to another correct memory address. + // + if (((UINTN) FvHeader % sizeof (UINT64)) != 0) { + DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) CmpSectionLength - sizeof (EFI_COMMON_SECTION_HEADER)), sizeof (UINT64)); + if (DstBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (DstBuffer, FvHeader, (UINTN) CmpSectionLength - sizeof (EFI_COMMON_SECTION_HEADER)); + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer; + } + + // + // Build new FvHob for new decompressed Fv image. + // + BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength); + + // + // Set the original FvHob to unused. + // + if (OrigHob != NULL) { + OrigHob->Header->HobType = EFI_HOB_TYPE_UNUSED; + } + + // + // return found FvImage data. + // + *Pe32Data = (VOID *) FvHeader; + return EFI_SUCCESS; + } + } + } + OccupiedCmpSectionLength = GET_OCCUPIED_SIZE (CmpSectionLength, 4); + CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength); + } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize); + } + // + // End of the decompression activity + // + + Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength); + FileSize = FfsFileHeader->Size[0] & 0xFF; + FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00; + FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000; + FileSize &= 0x00FFFFFF; + } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize); + + // + // search all sections (compression and non compression) in this FFS, don't + // find expected section. + // + return EFI_NOT_FOUND; + } else { + // + // For those FFS that doesn't contain compression section, directly search + // PE or TE section in this FFS. + // + + Status = PeiServicesFfsFindSectionData ( + EFI_SECTION_PE32, + FfsFileHeader, + &SectionData + ); + + if (EFI_ERROR (Status)) { + Status = PeiServicesFfsFindSectionData ( + EFI_SECTION_TE, + FfsFileHeader, + &SectionData + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + } + + *Pe32Data = SectionData; + + return EFI_SUCCESS; +} + diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c new file mode 100644 index 0000000000..d3fbcb2e08 --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c @@ -0,0 +1,136 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DxeLoadFunc.c + +Abstract: + + Ia32-specifc functionality for DxeLoad. + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "DxeIpl.h" +#include "VirtualMemory.h" + +// +// Global Descriptor Table (GDT) +// +GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT gGdtEntries [] = { +/* selector { Global Segment Descriptor } */ +/* 0x00 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //null descriptor +/* 0x08 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear data segment descriptor +/* 0x10 */ {{0xffff, 0, 0, 0xf, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear code segment descriptor +/* 0x18 */ {{0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor +/* 0x20 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system code segment descriptor +/* 0x28 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor +/* 0x30 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor +/* 0x38 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 1, 0, 1, 0}}, //system code segment descriptor +/* 0x40 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor +}; + +// +// IA32 Gdt register +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR gGdt = { + sizeof (gGdtEntries) - 1, + (UINTN) gGdtEntries + }; + +VOID +HandOffToDxeCore ( + IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint, + IN EFI_PEI_HOB_POINTERS HobList, + IN EFI_PEI_PPI_DESCRIPTOR *EndOfPeiSignal + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS BaseOfStack; + EFI_PHYSICAL_ADDRESS TopOfStack; + UINTN PageTables; + + Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack); + ASSERT_EFI_ERROR (Status); + + if (FeaturePcdGet(PcdDxeIplSwitchToLongMode)) { + // + // Compute the top of the stack we were allocated, which is used to load X64 dxe core. + // Pre-allocate a 32 bytes which confroms to x64 calling convention. + // + // The first four parameters to a function are passed in rcx, rdx, r8 and r9. + // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the + // register parameters is reserved on the stack, in case the called function + // wants to spill them; this is important if the function is variadic. + // + TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32; + + // + // X64 Calling Conventions requires that the stack must be aligned to 16 bytes + // + TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16); + + // + // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA + // memory, it may be corrupted when copying FV to high-end memory + // + AsmWriteGdtr (&gGdt); + // + // Create page table and save PageMapLevel4 to CR3 + // + PageTables = CreateIdentityMappingPageTables (); + + // + // End of PEI phase singal + // + Status = PeiServicesInstallPpi (EndOfPeiSignal); + ASSERT_EFI_ERROR (Status); + + AsmWriteCr3 (PageTables); + // + // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded. + // Call x64 drivers passing in single argument, a pointer to the HOBs. + // + AsmEnablePaging64 ( + SYS_CODE64_SEL, + DxeCoreEntryPoint, + (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw), + 0, + TopOfStack + ); + } else { + // + // Compute the top of the stack we were allocated. Pre-allocate a UINTN + // for safety. + // + TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT; + TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); + + // + // End of PEI phase singal + // + Status = PeiServicesInstallPpi (EndOfPeiSignal); + ASSERT_EFI_ERROR (Status); + + SwitchStack ( + (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint, + HobList.Raw, + NULL, + (VOID *) (UINTN) TopOfStack + ); + } +} + diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c new file mode 100644 index 0000000000..f7bef7eb3e --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/ImageRead.c @@ -0,0 +1,117 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ImageRead.c + +Abstract: + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "DxeIpl.h" + +EFI_STATUS +EFIAPI +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + + FileOffset - The offset, in bytes, into the file to read + + ReadSize - The number of bytes to read from the file starting at FileOffset + + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + UINT8 *Destination32; + UINT8 *Source32; + UINTN Length; + + + Destination32 = Buffer; + Source32 = (UINT8 *) ((UINTN) FileHandle + FileOffset); + + // + // This function assumes 32-bit alignment to increase performance + // +// ASSERT (ALIGN_POINTER (Destination32, sizeof (UINT32)) == Destination32); +// ASSERT (ALIGN_POINTER (Source32, sizeof (UINT32)) == Source32); + + Length = *ReadSize; + while (Length--) { + *(Destination32++) = *(Source32++); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetImageReadFunction ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + Support routine to return the PE32 Image Reader. + If the PeiImageRead() function is less than a page + in legnth. If the function is more than a page the DXE IPL will crash!!!! + +Arguments: + ImageContext - The context of the image being loaded + +Returns: + EFI_SUCCESS - If Image function location is found + +--*/ +{ + VOID *MemoryBuffer; + + if (gInMemory) { + ImageContext->ImageRead = PeiImageRead; + return EFI_SUCCESS; + } + + // + // BugBug; This code assumes PeiImageRead() is less than a page in size! + // Allocate a page so we can shaddow the read function from FLASH into + // memory to increase performance. + // + + MemoryBuffer = AllocateCopyPool (0x400, (VOID *)(UINTN) PeiImageRead); + ASSERT (MemoryBuffer != NULL); + + ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer; + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.c new file mode 100644 index 0000000000..f4a6a4faba --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.c @@ -0,0 +1,173 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + VirtualMemory.c + +Abstract: + + x64 Virtual Memory Management Services in the form of an IA-32 driver. + Used to establish a 1:1 Virtual to Physical Mapping that is required to + enter Long Mode (x64 64-bit mode). + + While we make a 1:1 mapping (identity mapping) for all physical pages + we still need to use the MTRR's to ensure that the cachability attirbutes + for all memory regions is correct. + + The basic idea is to use 2MB page table entries where ever possible. If + more granularity of cachability is required then 4K page tables are used. + + References: + 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel + 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel + 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "VirtualMemory.h" + +UINTN +CreateIdentityMappingPageTables ( + VOID + ) +/*++ + +Routine Description: + + Allocates and fills in the Page Directory and Page Table Entries to + establish a 1:1 Virtual to Physical mapping. + +Arguments: + + NumberOfProcessorPhysicalAddressBits - Number of processor address bits to use. + Limits the number of page table entries + to the physical address space. + +Returns: + + EFI_SUCCESS The 1:1 Virtual to Physical identity mapping was created + +--*/ +{ + UINT8 PhysicalAddressBits; + EFI_PHYSICAL_ADDRESS PageAddress; + UINTN IndexOfPml4Entries; + UINTN IndexOfPdpEntries; + UINTN IndexOfPageDirectoryEntries; + UINTN NumberOfPml4EntriesNeeded; + UINTN NumberOfPdpEntriesNeeded; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMap; + PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; + PAGE_TABLE_ENTRY *PageDirectoryEntry; + UINTN TotalPagesNum; + UINTN BigPageAddress; + VOID *Hob; + + // + // Get physical address bits supported from CPU HOB. + // + PhysicalAddressBits = 36; + + Hob = GetFirstHob (EFI_HOB_TYPE_CPU); + if (Hob != NULL) { + PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; + } + + // + // Calculate the table entries needed. + // + if (PhysicalAddressBits <= 39 ) { + NumberOfPml4EntriesNeeded = 1; + NumberOfPdpEntriesNeeded = 1 << (PhysicalAddressBits - 30); + } else { + NumberOfPml4EntriesNeeded = 1 << (PhysicalAddressBits - 39); + NumberOfPdpEntriesNeeded = 512; + } + + // + // Pre-allocate big pages to avoid later allocations. + // + TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1; + BigPageAddress = (UINTN) AllocatePages (TotalPagesNum); + ASSERT (BigPageAddress != 0); + + // + // By architecture only one PageMapLevel4 exists - so lets allocate storage for it. + // + PageMap = (VOID *) BigPageAddress; + BigPageAddress += EFI_PAGE_SIZE; + + PageMapLevel4Entry = PageMap; + PageAddress = 0; + for (IndexOfPml4Entries = 0; IndexOfPml4Entries < NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, PageMapLevel4Entry++) { + // + // Each PML4 entry points to a page of Page Directory Pointer entires. + // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop. + // + PageDirectoryPointerEntry = (VOID *) BigPageAddress; + BigPageAddress += EFI_PAGE_SIZE; + + // + // Make a PML4 Entry + // + PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry; + PageMapLevel4Entry->Bits.ReadWrite = 1; + PageMapLevel4Entry->Bits.Present = 1; + + for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { + // + // Each Directory Pointer entries points to a page of Page Directory entires. + // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop. + // + PageDirectoryEntry = (VOID *) BigPageAddress; + BigPageAddress += EFI_PAGE_SIZE; + + // + // Fill in a Page Directory Pointer Entries + // + PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry; + PageDirectoryPointerEntry->Bits.ReadWrite = 1; + PageDirectoryPointerEntry->Bits.Present = 1; + + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += 0x200000) { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry->Uint64 = (UINT64)PageAddress; + PageDirectoryEntry->Bits.ReadWrite = 1; + PageDirectoryEntry->Bits.Present = 1; + PageDirectoryEntry->Bits.MustBe1 = 1; + + } + } + } + + // + // For the PML4 entries we are not using fill in a null entry. + // For now we just copy the first entry. + // + for (; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Entry++) { + CopyMem ( + PageMapLevel4Entry, + PageMap, + sizeof (PAGE_MAP_AND_DIRECTORY_POINTER) + ); + } + + return (UINTN)PageMap; // FIXME +} + diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h b/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h new file mode 100644 index 0000000000..4e6614ecfb --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h @@ -0,0 +1,112 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + VirtualMemory.h + +Abstract: + + x64 Long Mode Virtual Memory Management Definitions + + References: + 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel + 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel + 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel + 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming +--*/ +#ifndef _VIRTUAL_MEMORY_H_ +#define _VIRTUAL_MEMORY_H_ + + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#define SYS_CODE64_SEL 0x38 + +#pragma pack(1) + +typedef union { + struct { + UINT32 LimitLow : 16; + UINT32 BaseLow : 16; + UINT32 BaseMid : 8; + UINT32 Type : 4; + UINT32 System : 1; + UINT32 Dpl : 2; + UINT32 Present : 1; + UINT32 LimitHigh : 4; + UINT32 Software : 1; + UINT32 Reserved : 1; + UINT32 DefaultSize : 1; + UINT32 Granularity : 1; + UINT32 BaseHigh : 8; + } Bits; + UINT64 Uint64; +} IA32_GDT; + +// +// Page-Map Level-4 Offset (PML4) and +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB +// + +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:2; // Must Be Zero + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} PAGE_MAP_AND_DIRECTORY_POINTER; + +// +// Page Table Entry 2MB +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PAT:1; // + UINT64 MustBeZero:8; // Must be zero; + UINT64 PageTableBaseAddress:31; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_ENTRY; + +#pragma pack() + +UINTN +CreateIdentityMappingPageTables ( + VOID + ) +; + +#endif diff --git a/MdeModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c new file mode 100644 index 0000000000..3feb2e5ee5 --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c @@ -0,0 +1,77 @@ +/*++ + +Copyright (c) 2006 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + IpfDxeLoad.c + +Abstract: + + Ipf-specifc functionality for DxeLoad. + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "DxeIpl.h" + +VOID +HandOffToDxeCore ( + IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint, + IN EFI_PEI_HOB_POINTERS HobList, + IN EFI_PEI_PPI_DESCRIPTOR *EndOfPeiSignal + ) +{ + VOID *BaseOfStack; + VOID *TopOfStack; + VOID *BspStore; + EFI_STATUS Status; + + // + // Allocate 128KB for the Stack + // + BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE)); + ASSERT (BaseOfStack != NULL); + + // + // Allocate 16KB for the BspStore + // + BspStore = AllocatePages (EFI_SIZE_TO_PAGES (BSP_STORE_SIZE)); + ASSERT (BspStore != NULL); + // + // Build BspStoreHob + // + BuildBspStoreHob ((EFI_PHYSICAL_ADDRESS) (UINTN) BspStore, BSP_STORE_SIZE, EfiBootServicesData); + + // + // Compute the top of the stack we were allocated. Pre-allocate a UINTN + // for safety. + // + TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT); + TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); + + // + // End of PEI phase singal + // + Status = PeiServicesInstallPpi (EndOfPeiSignal); + ASSERT_EFI_ERROR (Status); + + SwitchStack ( + (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint, + HobList.Raw, + NULL, + TopOfStack, + BspStore + ); +} diff --git a/MdeModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c b/MdeModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c new file mode 100644 index 0000000000..5002fe8c67 --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c @@ -0,0 +1,77 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ImageRead.c + +Abstract: + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "DxeIpl.h" + +EFI_STATUS +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + + FileOffset - The offset, in bytes, into the file to read + + ReadSize - The number of bytes to read from the file starting at FileOffset + + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + volatile UINTN Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetImageReadFunction ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + ImageContext->ImageRead = PeiImageRead; + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c new file mode 100644 index 0000000000..1d5709af5e --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c @@ -0,0 +1,65 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DxeLoadFunc.c + +Abstract: + + Ia32-specifc functionality for DxeLoad. + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "DxeIpl.h" + +VOID +HandOffToDxeCore ( + IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint, + IN EFI_PEI_HOB_POINTERS HobList, + IN EFI_PEI_PPI_DESCRIPTOR *EndOfPeiSignal + ) +{ + VOID *BaseOfStack; + VOID *TopOfStack; + EFI_STATUS Status; + + // + // Allocate 128KB for the Stack + // + BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE)); + ASSERT (BaseOfStack != NULL); + + // + // Compute the top of the stack we were allocated. Pre-allocate a UINTN + // for safety. + // + TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT); + TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); + + // + // End of PEI phase singal + // + Status = PeiServicesInstallPpi (EndOfPeiSignal); + ASSERT_EFI_ERROR (Status); + + SwitchStack ( + (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint, + HobList.Raw, + NULL, + TopOfStack + ); +} diff --git a/MdeModulePkg/Include/Common/DecompressLibraryHob.h b/MdeModulePkg/Include/Common/DecompressLibraryHob.h new file mode 100644 index 0000000000..ee7b8a2ea1 --- /dev/null +++ b/MdeModulePkg/Include/Common/DecompressLibraryHob.h @@ -0,0 +1,47 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DecompressLibraryHob.h + +Abstract: + + Declaration of HOB that is used to pass decompressor library functions from PEI to DXE + +--*/ + +#ifndef __DECOMPRESS_LIBRARY_HOB_H__ +#define __DECOMPRESS_LIBRARY_HOB_H__ + +typedef +RETURN_STATUS +(EFIAPI *DECOMPRESS_LIBRARY_GET_INFO) ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); + +typedef +RETURN_STATUS +(EFIAPI *DECOMPRESS_LIBRARY_DECOMPRESS) ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ); + +typedef struct { + DECOMPRESS_LIBRARY_GET_INFO GetInfo; + DECOMPRESS_LIBRARY_DECOMPRESS Decompress; +} DECOMPRESS_LIBRARY; + +#endif diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index b8a09d12bd..b4b46d9379 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -67,6 +67,9 @@ ##gEfiPeiPeCoffLoaderGuid will be removed in future gEfiPeiPeCoffLoaderGuid = { 0xd8117cff, 0x94a6, 0x11d4, {0x9a, 0x3a, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } } gEfiPeiCorePrivateGuid = { 0xd641a0f5, 0xcb7c, 0x4846, { 0xa3, 0x80, 0x1d, 0x01, 0xb4, 0xd9, 0xe3, 0xb9 }} + gEfiEndOfPeiSignalPpiGuid = { 0x605EA650, 0xC65C, 0x42e1, { 0xBA, 0x80, 0x91, 0xA5, 0x2A, 0xB6, 0x18, 0xC6 }} + gEfiPeiFvFileLoaderPpiGuid = { 0x7e1f0d85, 0x04ff, 0x4bb2, { 0x86, 0x6a, 0x31, 0xa2, 0x99, 0x6a, 0x48, 0xa8 }} + ################################################################################ # @@ -162,6 +165,6 @@ [PcdsFeatureFlag.IA32] - PcdDxeIplSwitchToLongMode|0x0001003b|gEfiEdkModulePkgTokenSpaceGuid|BOOLEAN|TRUE + PcdDxeIplSwitchToLongMode|0x0001003b|gEfiMdeModulePkgTokenSpaceGuid|BOOLEAN|TRUE diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index d01a1477f3..898045306e 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -54,6 +54,11 @@ PrintLib|${WORKSPACE}/MdePkg/Library/BasePrintLib/BasePrintLib.inf TimerLib|${WORKSPACE}/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf UefiDecompressLib|${WORKSPACE}/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + EdkPeCoffLoaderLib|${WORKSPACE}/MdeModulePkg/Library/PeiDxePeCoffLoaderLib/PeCoffLoaderLib.inf + ReportStatusCodeLib|${WORKSPACE}/IntelFrameworkPkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf + CustomDecompressLib|${WORKSPACE}/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + HiiLib|${WORKSPACE}/IntelFrameworkPkg/Library/HiiLibFramework/HiiLib.inf + [LibraryClasses.IA32] IoLib|${WORKSPACE}/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf @@ -119,6 +124,7 @@ FvbServiceLib|${WORKSPACE}/MdeModulePkg/Library/EdkFvbServiceLib/EdkFvbServiceLib.inf ReportStatusCodeLib|${WORKSPACE}/IntelFrameworkPkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf ScsiLib|$(WORKSPACE)/MdePkg/Library/UefiScsiLib/UefiScsiLib.inf + FrameworkHiiLib|$(WORKSPACE)/IntelFrameworkPkg/Library/FrameworkHiiLib/HiiLib.inf [LibraryClasses.common.DXE_RUNTIME_DRIVER] HobLib|${WORKSPACE}/MdePkg/Library/DxeHobLib/DxeHobLib.inf @@ -302,9 +308,19 @@ PcdPeiPcdDatabaseCallbackOnSetEnabled|gEfiEdkModulePkgTokenSpaceGuid|TRUE PcdPeiPcdDatabaseExEnabled|gEfiEdkModulePkgTokenSpaceGuid|TRUE PcdNtEmulatorEnable|gEfiEdkModulePkgTokenSpaceGuid|FALSE + PcdDevicePathSupportDevicePathFromText|gEfiEdkModulePkgTokenSpaceGuid|FALSE + PcdDevicePathSupportDevicePathToText|gEfiEdkModulePkgTokenSpaceGuid|FALSE + PcdDxeIplSupportCustomDecompress|gEfiEdkModulePkgTokenSpaceGuid|TRUE + PcdDxeIplBuildShareCodeHobs|gEfiEdkModulePkgTokenSpaceGuid|FALSE + PcdDxeIplSupportEfiDecompress|gEfiEdkModulePkgTokenSpaceGuid|TRUE + PcdDxeIplSupportTianoDecompress|gEfiEdkModulePkgTokenSpaceGuid|TRUE + PcdDxeIplSupportCustomDecompress|gEfiEdkModulePkgTokenSpaceGuid|TRUE # PcdStatusCodeUseOEM|gEfiIntelFrameworkModulePkgTokenSpaceGuid|FALSE +[PcdsFeatureFlag.IA32] + PcdDxeIplSwitchToLongMode|gEfiMdeModulePkgTokenSpaceGuid|TRUE + [PcdsFixedAtBuild.common] PcdMaximumUnicodeStringLength|gEfiMdePkgTokenSpaceGuid|1000000 PcdMaximumAsciiStringLength|gEfiMdePkgTokenSpaceGuid|1000000 @@ -379,6 +395,13 @@ $(WORKSPACE)/MdeModulePkg/Universal/PCD/Pei/Pcd.inf $(WORKSPACE)/MdeModulePkg/Core/Dxe/DxeMain.inf $(WORKSPACE)/MdeModulePkg/Core/Pei/PeiMain.inf + ${WORKSPACE}/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.inf + ${WORKSPACE}/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.inf + ${WORKSPACE}/MdeModulePkg/Universal/DevicePathDxe/DevicePath.inf + ${WORKSPACE}/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.inf + ${WORKSPACE}/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.inf + ${WORKSPACE}/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf + [Components.X64] ${WORKSPACE}/MdeModulePkg/Application/HelloWorld/HelloWorld.inf diff --git a/MdeModulePkg/Universal/Console/ConPlatformDxe/CommonHeader.h b/MdeModulePkg/Universal/Console/ConPlatformDxe/CommonHeader.h new file mode 100644 index 0000000000..5a5ef994d2 --- /dev/null +++ b/MdeModulePkg/Universal/Console/ConPlatformDxe/CommonHeader.h @@ -0,0 +1,54 @@ +/**@file + Common header file shared by all source files. + + This file includes package header files, library classes and protocol, PPI & GUID definitions. + + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + + +// +// The package level header files this module uses +// +#include + +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include +// +// Driver Binding Externs +// +extern EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextInDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gConPlatformComponentName; +extern EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextOutDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gConPlatformComponentName; + +#endif diff --git a/MdeModulePkg/Universal/Console/ConPlatformDxe/ComponentName.c b/MdeModulePkg/Universal/Console/ConPlatformDxe/ComponentName.c new file mode 100644 index 0000000000..146eee62c6 --- /dev/null +++ b/MdeModulePkg/Universal/Console/ConPlatformDxe/ComponentName.c @@ -0,0 +1,146 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +// +// Include common header file for this module. +// + + +#include "ConPlatform.h" +#include "ComponentName.h" + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gConPlatformComponentName = { + ConPlatformComponentNameGetDriverName, + ConPlatformComponentNameGetControllerName, + "eng" +}; + +STATIC EFI_UNICODE_STRING_TABLE mConPlatformDriverNameTable[] = { + { + "eng", + L"Platform Console Management Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +ConPlatformComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gConPlatformComponentName.SupportedLanguages, + mConPlatformDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +ConPlatformComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/MdeModulePkg/Universal/Console/ConPlatformDxe/ComponentName.h b/MdeModulePkg/Universal/Console/ConPlatformDxe/ComponentName.h new file mode 100644 index 0000000000..17c43481b6 --- /dev/null +++ b/MdeModulePkg/Universal/Console/ConPlatformDxe/ComponentName.h @@ -0,0 +1,45 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ComponentName.h + +Abstract: + +--*/ + +#ifndef CON_MANAGE_COMPONENT_NAME_H_ +#define CON_MANAGE_COMPONENT_NAME_H_ + + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +ConPlatformComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +ConPlatformComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +#endif diff --git a/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.c b/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.c new file mode 100644 index 0000000000..d86ea4766f --- /dev/null +++ b/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.c @@ -0,0 +1,950 @@ +/*++ + +Copyright (c) 2006 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ConPlatform.c + +Abstract: + +--*/ + +#include + +#include "ConPlatform.h" + + +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include +// +// Driver Binding Externs +// +extern EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextInDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gConPlatformComponentName; +extern EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextOutDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gConPlatformComponentName; + +EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextInDriverBinding = { + ConPlatformTextInDriverBindingSupported, + ConPlatformTextInDriverBindingStart, + ConPlatformTextInDriverBindingStop, + 0xa, + NULL, + NULL +}; + +EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextOutDriverBinding = { + ConPlatformTextOutDriverBindingSupported, + ConPlatformTextOutDriverBindingStart, + ConPlatformTextOutDriverBindingStop, + 0xa, + NULL, + NULL +}; + +/** + The user Entry Point for module ConPlatform. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeConPlatform( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gConPlatformTextInDriverBinding, + ImageHandle, + &gConPlatformComponentName, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Status = EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gConPlatformTextOutDriverBinding, + NULL, + &gConPlatformComponentName, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + + return Status; +} + + +EFI_STATUS +EFIAPI +ConPlatformTextInDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Supported + +Arguments: + (Standard DriverBinding Protocol Supported() function) + +Returns: + + None + +--*/ +{ + return ConPlatformDriverBindingSupported ( + This, + ControllerHandle, + RemainingDevicePath, + &gEfiSimpleTextInProtocolGuid + ); +} + +EFI_STATUS +EFIAPI +ConPlatformTextOutDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Supported + +Arguments: + (Standard DriverBinding Protocol Supported() function) + +Returns: + + None + +--*/ +{ + return ConPlatformDriverBindingSupported ( + This, + ControllerHandle, + RemainingDevicePath, + &gEfiSimpleTextOutProtocolGuid + ); +} + +EFI_STATUS +ConPlatformDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, + IN EFI_GUID *ProtocolGuid + ) +/*++ + +Routine Description: + Supported + +Arguments: + (Standard DriverBinding Protocol Supported() function) + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + VOID *Interface; + + // + // Test to see if this is a physical device by checking to see if + // it has a Device Path Protocol + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + NULL, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Test to see if this device supports the Simple Text Output Protocol + // + Status = gBS->OpenProtocol ( + ControllerHandle, + ProtocolGuid, + (VOID **) &Interface, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + ControllerHandle, + ProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConPlatformTextInDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + +Arguments: + (Standard DriverBinding Protocol Start() function) + +Returns: + + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn; + + // + // 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)) { + return Status; + } + // + // Open the Simple Input Protocol BY_DRIVER + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &TextIn, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the device handle, if it is a hot plug device, + // do not put the device path into ConInDev, and install + // gEfiConsoleInDeviceGuid to the device handle directly. + // The policy is, make hot plug device plug in and play immediately. + // + if (IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) { + gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiConsoleInDeviceGuid, + NULL, + NULL + ); + } else { + // + // Append the device path to the ConInDev environment variable + // + ConPlatformUpdateDeviceVariable ( + VarConsoleInpDev, + DevicePath, + APPEND + ); + + // + // If the device path is an instance in the ConIn environment variable, + // then install EfiConsoleInDeviceGuid onto ControllerHandle + // + Status = ConPlatformUpdateDeviceVariable ( + VarConsoleInp, + DevicePath, + CHECK + ); + + if (!EFI_ERROR (Status)) { + gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiConsoleInDeviceGuid, + NULL, + NULL + ); + } else { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiSimpleTextInProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConPlatformTextOutDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + +Arguments: + (Standard DriverBinding Protocol Start() function) + +Returns: + + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; + BOOLEAN NeedClose; + + NeedClose = TRUE; + + // + // 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)) { + return Status; + } + // + // Open the Simple Text Output Protocol BY_DRIVER + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the device handle, if it is a hot plug device, + // do not put the device path into ConOutDev and StdErrDev, + // and install gEfiConsoleOutDeviceGuid to the device handle directly. + // The policy is, make hot plug device plug in and play immediately. + // + if (IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) { + gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiConsoleOutDeviceGuid, + NULL, + NULL + ); + } else { + // + // Append the device path to the ConOutDev environment variable + // + ConPlatformUpdateDeviceVariable ( + VarConsoleOutDev, + DevicePath, + APPEND + ); + // + // Append the device path to the StdErrDev environment variable + // + ConPlatformUpdateDeviceVariable ( + VarErrorOutDev, + DevicePath, + APPEND + ); + + // + // If the device path is an instance in the ConOut environment variable, + // then install EfiConsoleOutDeviceGuid onto ControllerHandle + // + Status = ConPlatformUpdateDeviceVariable ( + VarConsoleOut, + DevicePath, + CHECK + ); + + if (!EFI_ERROR (Status)) { + NeedClose = FALSE; + Status = gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiConsoleOutDeviceGuid, + NULL, + NULL + ); + } + // + // If the device path is an instance in the StdErr environment variable, + // then install EfiStandardErrorDeviceGuid onto ControllerHandle + // + Status = ConPlatformUpdateDeviceVariable ( + VarErrorOut, + DevicePath, + CHECK + ); + if (!EFI_ERROR (Status)) { + NeedClose = FALSE; + gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiStandardErrorDeviceGuid, + NULL, + NULL + ); + } + + if (NeedClose) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiSimpleTextOutProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConPlatformTextInDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + (Standard DriverBinding Protocol Stop() function) + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + // + // hot plug device is not included into the console associated variables, + // so no need to check variable for those hot plug devices. + // + if (!IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) { + // + // 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 + // + ConPlatformUpdateDeviceVariable ( + VarConsoleInpDev, + DevicePath, + DELETE + ); + } + } + // + // Uninstall the Console Device GUIDs from Controller Handle + // + ConPlatformUnInstallProtocol ( + This, + ControllerHandle, + &gEfiConsoleInDeviceGuid + ); + + // + // Close the Simple Input Protocol + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiSimpleTextInProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConPlatformTextOutDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + (Standard DriverBinding Protocol Stop() function) + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + // + // hot plug device is not included into the console associated variables, + // so no need to check variable for those hot plug devices. + // + if (!IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) { + // + // 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 ConOutDev, and StdErrDev + // + ConPlatformUpdateDeviceVariable ( + VarConsoleOutDev, + DevicePath, + DELETE + ); + ConPlatformUpdateDeviceVariable ( + VarErrorOutDev, + DevicePath, + DELETE + ); + } + } + // + // Uninstall the Console Device GUIDs from Controller Handle + // + ConPlatformUnInstallProtocol ( + This, + ControllerHandle, + &gEfiConsoleOutDeviceGuid + ); + + ConPlatformUnInstallProtocol ( + This, + ControllerHandle, + &gEfiStandardErrorDeviceGuid + ); + + // + // Close the Simple Text Output Protocol + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiSimpleTextOutProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return EFI_SUCCESS; +} + + +VOID +ConPlatformUnInstallProtocol ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_GUID *ProtocolGuid + ) +{ + EFI_STATUS Status; + + Status = gBS->OpenProtocol ( + Handle, + ProtocolGuid, + NULL, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + + if (!EFI_ERROR (Status)) { + gBS->UninstallMultipleProtocolInterfaces ( + Handle, + ProtocolGuid, + NULL, + NULL + ); + } + + return ; +} + +VOID * +ConPlatformGetVariable ( + IN CHAR16 *Name + ) +/*++ + +Routine Description: + Read the EFI variable (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 + +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; + UINTN BufferSize; + + BufferSize = 0; + Buffer = NULL; + + // + // Test to see if the variable exists. If it doesn't reuturn NULL + // + Status = gRT->GetVariable ( + Name, + &gEfiGlobalVariableGuid, + NULL, + &BufferSize, + Buffer + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Allocate the buffer to return + // + Buffer = AllocatePool (BufferSize); + if (Buffer == NULL) { + return NULL; + } + // + // Read variable into the allocated buffer. + // + Status = gRT->GetVariable ( + Name, + &gEfiGlobalVariableGuid, + NULL, + &BufferSize, + Buffer + ); + if (EFI_ERROR (Status)) { + FreePool (Buffer); + Buffer = NULL; + } + } + + return Buffer; +} + +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 *TempDevicePath1; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath2; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; + UINTN Size; + + // + // The passed in DevicePath should not be NULL + // + if ((!Multi) || (!Single)) { + return EFI_NOT_FOUND; + } + // + // if performing Delete operation, the NewDevicePath must not be NULL. + // + TempDevicePath1 = NULL; + + DevicePath = Multi; + DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size); + + // + // search for the match of 'Single' in 'Multi' + // + while (DevicePathInst) { + if (CompareMem (Single, DevicePathInst, Size) == 0) { + if (!Delete) { + FreePool (DevicePathInst); + return EFI_SUCCESS; + } + } else { + if (Delete) { + TempDevicePath2 = AppendDevicePathInstance ( + TempDevicePath1, + DevicePathInst + ); + if (TempDevicePath1 != NULL) { + FreePool (TempDevicePath1); + } + TempDevicePath1 = TempDevicePath2; + } + } + + FreePool (DevicePathInst); + DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size); + } + + if (Delete) { + *NewDevicePath = TempDevicePath1; + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +ConPlatformUpdateDeviceVariable ( + IN CHAR16 *VariableName, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONPLATFORM_VAR_OPERATION Operation + ) +/*++ + +Routine Description: + + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *VariableDevicePath; + EFI_DEVICE_PATH_PROTOCOL *NewVariableDevicePath; + + VariableDevicePath = NULL; + NewVariableDevicePath = NULL; + + // + // Get Variable according to variable name. + // The memory for Variable is allocated within ConPlatformGetVarible(), + // it is the caller's responsibility to free the memory before return. + // + VariableDevicePath = ConPlatformGetVariable (VariableName); + + if (Operation != DELETE) { + + Status = ConPlatformMatchDevicePaths ( + VariableDevicePath, + DevicePath, + NULL, + FALSE + ); + + if ((Operation == CHECK) || (!EFI_ERROR (Status))) { + // + // The device path is already in the variable + // + if (VariableDevicePath != NULL) { + FreePool (VariableDevicePath); + } + + return Status; + } + // + // The device path is not in variable. Append DevicePath to the + // environment variable that is a multi-instance device path. + // + Status = EFI_SUCCESS; + NewVariableDevicePath = AppendDevicePathInstance ( + VariableDevicePath, + DevicePath + ); + if (NewVariableDevicePath == NULL) { + Status = 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 (VariableDevicePath != NULL) { + FreePool (VariableDevicePath); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gRT->SetVariable ( + VariableName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + GetDevicePathSize (NewVariableDevicePath), + NewVariableDevicePath + ); + + FreePool (NewVariableDevicePath); + + 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; +} diff --git a/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.h b/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.h new file mode 100644 index 0000000000..a1035156e5 --- /dev/null +++ b/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.h @@ -0,0 +1,132 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ConPlatform.h + +Abstract: + +--*/ + +#ifndef CON_MANAGE_H_ +#define CON_MANAGE_H_ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#define VarConsoleInpDev L"ConInDev" +#define VarConsoleInp L"ConIn" +#define VarConsoleOutDev L"ConOutDev" +#define VarConsoleOut L"ConOut" +#define VarErrorOutDev L"ErrOutDev" +#define VarErrorOut L"ErrOut" + +typedef enum { + CHECK, + APPEND, + DELETE +} CONPLATFORM_VAR_OPERATION; + +EFI_STATUS +ConPlatformDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, + IN EFI_GUID *ProtocolGuid + ); + +EFI_STATUS +EFIAPI +ConPlatformTextInDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +ConPlatformTextOutDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +ConPlatformTextInDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +ConPlatformTextOutDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +ConPlatformTextInDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +EFI_STATUS +EFIAPI +ConPlatformTextOutDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +VOID +ConPlatformUnInstallProtocol ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_GUID *ProtocolGuid + ); + +VOID * +ConPlatformGetVariable ( + IN CHAR16 *Name + ); + +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 + ); + +EFI_STATUS +ConPlatformUpdateDeviceVariable ( + IN CHAR16 *VariableName, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONPLATFORM_VAR_OPERATION Operation + ); + +BOOLEAN +IsHotPlugDevice ( + EFI_HANDLE DriverBindingHandle, + EFI_HANDLE ControllerHandle + ); + +#endif diff --git a/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.inf b/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.inf new file mode 100644 index 0000000000..ede86983e9 --- /dev/null +++ b/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.inf @@ -0,0 +1,112 @@ +#/** @file +# Console Platfrom Driver +# +# Console Platfrom DXE Driver, install Console protocols +# Copyright (c) 2006 - 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ConPlatform + FILE_GUID = 51ccf399-4fdf-4e55-a45b-e123f84d456a + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + ENTRY_POINT = InitializeConPlatform + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gConPlatformTextInDriverBinding +# COMPONENT_NAME = gConPlatformComponentName +# DRIVER_BINDING = gConPlatformTextOutDriverBinding +# COMPONENT_NAME = gConPlatformComponentName +# + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ + +[Sources.common] + ComponentName.c + ComponentName.h + ConPlatform.h + ConPlatform.c + CommonHeader.h + + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + MdePkg/MdePkg.dec + + +################################################################################ +# +# Library Class Section - list of Library Classes that are required for +# this module. +# +################################################################################ + +[LibraryClasses] + MemoryAllocationLib + DevicePathLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + DebugLib + + +################################################################################ +# +# Guid C Name Section - list of Guids that this module uses or produces. +# +################################################################################ + +[Guids] + gEfiGlobalVariableGuid # SOMETIMES_CONSUMED L"ErrOut" + + +################################################################################ +# +# Protocol C Name Section - list of Protocol and Protocol Notify C Names +# that this module uses or produces. +# +################################################################################ + +[Protocols] + gEfiHotPlugDeviceGuid # PROTOCOL TO_START + gEfiDevicePathProtocolGuid # PROTOCOL TO_START + gEfiSimpleTextInProtocolGuid # PROTOCOL TO_START + gEfiSimpleTextOutProtocolGuid # PROTOCOL TO_START + gEfiStandardErrorDeviceGuid # PROTOCOL BY_START + gEfiConsoleOutDeviceGuid # PROTOCOL BY_START + gEfiConsoleInDeviceGuid # PROTOCOL BY_START + diff --git a/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.msa b/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.msa new file mode 100644 index 0000000000..a4300e53f3 --- /dev/null +++ b/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.msa @@ -0,0 +1,135 @@ + + + + ConPlatform + UEFI_DRIVER + 51ccf399-4fdf-4e55-a45b-e123f84d456a + 1.0 + Console Platfrom Driver + Console Platfrom DXE Driver, install Console protocols + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + ConPlatform + + + + DebugLib + + + UefiDriverModelLib + + + UefiDriverEntryPoint + + + UefiLib + + + BaseMemoryLib + + + UefiBootServicesTableLib + + + UefiRuntimeServicesTableLib + + + DevicePathLib + + + MemoryAllocationLib + + + + ConPlatform.c + ConPlatform.h + ComponentName.h + ComponentName.c + + + + + + + + gEfiConsoleInDeviceGuid + + + gEfiConsoleOutDeviceGuid + + + gEfiStandardErrorDeviceGuid + + + gEfiSimpleTextOutProtocolGuid + + + gEfiSimpleTextInProtocolGuid + + + gEfiDevicePathProtocolGuid + + + gEfiHotPlugDeviceGuid + + + + + 0x0043 0x006F 0x006E 0x0049 0x006E 0x0044 0x0065 0x0076 + gEfiGlobalVariableGuid + L"ConInDev" global variable will be updated if the serial device is not a hot plug device. + + + 0x0043 0x006F 0x006E 0x0049 0x006E + gEfiGlobalVariableGuid + L"ConIn" global variable will be updated if the serial device is not a hot plug device. + + + 0x0043 0x006F 0x006E 0x004F 0x0075 0x0074 0x0044 0x0065 0x0076 + gEfiGlobalVariableGuid + L"ConOutDev" global variable will be updated if the serial device is not a hot plug device. + + + 0x0043 0x006F 0x006E 0x004F 0x0075 0x0074 + gEfiGlobalVariableGuid + L"ConOut" global variable will be updated if the serial device is not a hot plug device. + + + 0x0045 0x0072 0x0072 0x004F 0x0075 0x0074 0x0044 0x0065 0x0076 + gEfiGlobalVariableGuid + L"ErrOutDev" global variable will be updated if the serial device is not a hot plug device. + + + 0x0045 0x0072 0x0072 0x004F 0x0075 0x0074 + gEfiGlobalVariableGuid + L"ErrOut" global variable will be updated if the serial device is not a hot plug device. + + + + + gEfiGlobalVariableGuid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + gConPlatformTextInDriverBinding + gConPlatformComponentName + + + gConPlatformTextOutDriverBinding + gConPlatformComponentName + + + \ No newline at end of file diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/CommonHeader.h b/MdeModulePkg/Universal/Console/ConSplitterDxe/CommonHeader.h new file mode 100644 index 0000000000..7feaec4161 --- /dev/null +++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/CommonHeader.h @@ -0,0 +1,61 @@ +/**@file + Common header file shared by all source files. + + This file includes package header files, library classes and protocol, PPI & GUID definitions. + + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + + +// +// The package level header files this module uses +// +#include +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +// +// Driver Binding Externs +// +extern EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gConSplitterConInComponentName; +extern EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gConSplitterSimplePointerComponentName; +extern EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gConSplitterConOutComponentName; +extern EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gConSplitterStdErrComponentName; + + +#endif diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ComponentName.c b/MdeModulePkg/Universal/Console/ConSplitterDxe/ComponentName.c new file mode 100644 index 0000000000..6d1bf15a21 --- /dev/null +++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ComponentName.c @@ -0,0 +1,485 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "ConSplitter.h" + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gConSplitterConInComponentName = { + ConSplitterComponentNameGetDriverName, + ConSplitterConInComponentNameGetControllerName, + "eng" +}; + +EFI_COMPONENT_NAME_PROTOCOL gConSplitterSimplePointerComponentName = { + ConSplitterComponentNameGetDriverName, + ConSplitterSimplePointerComponentNameGetControllerName, + "eng" +}; + +EFI_COMPONENT_NAME_PROTOCOL gConSplitterConOutComponentName = { + ConSplitterComponentNameGetDriverName, + ConSplitterConOutComponentNameGetControllerName, + "eng" +}; + +EFI_COMPONENT_NAME_PROTOCOL gConSplitterStdErrComponentName = { + ConSplitterComponentNameGetDriverName, + ConSplitterStdErrComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mConSplitterDriverNameTable[] = { + { + "eng", + (CHAR16 *) L"Console Splitter Driver" + }, + { + NULL, + NULL + } +}; + +static EFI_UNICODE_STRING_TABLE mConSplitterConInControllerNameTable[] = { + { + "eng", + (CHAR16 *) L"Primary Console Input Device" + }, + { + NULL, + NULL + } +}; + +static EFI_UNICODE_STRING_TABLE mConSplitterSimplePointerControllerNameTable[] = { + { + "eng", + (CHAR16 *) L"Primary Simple Pointer Device" + }, + { + NULL, + NULL + } +}; + +static EFI_UNICODE_STRING_TABLE mConSplitterConOutControllerNameTable[] = { + { + "eng", + (CHAR16 *) L"Primary Console Output Device" + }, + { + NULL, + NULL + } +}; + +static EFI_UNICODE_STRING_TABLE mConSplitterStdErrControllerNameTable[] = { + { + "eng", + (CHAR16 *) L"Primary Standard Error Device" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +ConSplitterComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gConSplitterConInComponentName.SupportedLanguages, + mConSplitterDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +ConSplitterConInComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn; + // + // here ChildHandle is not an Optional parameter. + // + if (ChildHandle == NULL) { + return EFI_UNSUPPORTED; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &TextIn, + NULL, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + return LookupUnicodeString ( + Language, + gConSplitterConInComponentName.SupportedLanguages, + mConSplitterConInControllerNameTable, + ControllerName + ); +} + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer; + // + // here ChildHandle is not an Optional parameter. + // + if (ChildHandle == NULL) { + return EFI_UNSUPPORTED; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimplePointerProtocolGuid, + (VOID **) &SimplePointer, + NULL, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + return LookupUnicodeString ( + Language, + gConSplitterSimplePointerComponentName.SupportedLanguages, + mConSplitterSimplePointerControllerNameTable, + ControllerName + ); +} + +EFI_STATUS +EFIAPI +ConSplitterConOutComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; + // + // here ChildHandle is not an Optional parameter. + // + if (ChildHandle == NULL) { + return EFI_UNSUPPORTED; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut, + NULL, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + return LookupUnicodeString ( + Language, + gConSplitterConOutComponentName.SupportedLanguages, + mConSplitterConOutControllerNameTable, + ControllerName + ); +} + +EFI_STATUS +EFIAPI +ConSplitterStdErrComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ErrOut; + // + // here ChildHandle is not an Optional parameter. + // + if (ChildHandle == NULL) { + return EFI_UNSUPPORTED; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &ErrOut, + NULL, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + return LookupUnicodeString ( + Language, + gConSplitterStdErrComponentName.SupportedLanguages, + mConSplitterStdErrControllerNameTable, + ControllerName + ); +} diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c new file mode 100644 index 0000000000..ead6d654d8 --- /dev/null +++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c @@ -0,0 +1,3467 @@ +/**@file + Console Splitter Driver. Any Handle that attatched + EFI_CONSOLE_IDENTIFIER_PROTOCOL can be bound by this driver. + + So far it works like any other driver by opening a SimpleTextIn and/or + SimpleTextOut protocol with EFI_OPEN_PROTOCOL_BY_DRIVER attributes. The big + difference is this driver does not layer a protocol on the passed in + handle, or construct a child handle like a standard device or bus driver. + This driver produces three virtual handles as children, one for console input + splitter, one for console output splitter and one for error output splitter. + EFI_CONSOLE_SPLIT_PROTOCOL will be attatched onto each virtual handle to + identify the splitter type. + + Each virtual handle, that supports both the EFI_CONSOLE_SPLIT_PROTOCOL + and Console I/O protocol, will be produced in the driver entry point. + The virtual handle are added on driver entry and never removed. + Such design ensures sytem function well during none console device situation. + +Copyright (c) 2006 - 2007 Intel Corporation.
+All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "ConSplitter.h" + +// +// Global Variables +// +STATIC TEXT_IN_SPLITTER_PRIVATE_DATA mConIn = { + TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE, + (EFI_HANDLE) NULL, + { + ConSplitterTextInReset, + ConSplitterTextInReadKeyStroke, + (EFI_EVENT) NULL + }, + 0, + (EFI_SIMPLE_TEXT_INPUT_PROTOCOL **) NULL, + 0, + + { + ConSplitterSimplePointerReset, + ConSplitterSimplePointerGetState, + (EFI_EVENT) NULL, + (EFI_SIMPLE_POINTER_MODE *) NULL + }, + { + 0x10000, + 0x10000, + 0x10000, + TRUE, + TRUE + }, + 0, + (EFI_SIMPLE_POINTER_PROTOCOL **) NULL, + 0, + + FALSE, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + 0, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + (EFI_EVENT) NULL, + + FALSE, + FALSE +}; + +STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = { + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE, + (EFI_HANDLE) NULL, + { + ConSplitterTextOutReset, + ConSplitterTextOutOutputString, + ConSplitterTextOutTestString, + ConSplitterTextOutQueryMode, + ConSplitterTextOutSetMode, + ConSplitterTextOutSetAttribute, + ConSplitterTextOutClearScreen, + ConSplitterTextOutSetCursorPosition, + ConSplitterTextOutEnableCursor, + (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL + }, + { + 1, + 0, + 0, + 0, + 0, + FALSE, + }, + { + ConSpliterGraphicsOutputQueryMode, + ConSpliterGraphicsOutputSetMode, + ConSpliterGraphicsOutputBlt, + NULL + }, + (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL, + (TEXT_OUT_GOP_MODE *) NULL, + 0, + TRUE, + { + ConSpliterConsoleControlGetMode, + ConSpliterConsoleControlSetMode, + ConSpliterConsoleControlLockStdIn + }, + + 0, + (TEXT_OUT_AND_GOP_DATA *) NULL, + 0, + (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL, + 0, + (INT32 *) NULL, + + EfiConsoleControlScreenText, + 0, + 0, + (CHAR16 *) NULL, + (INT32 *) NULL +}; + +STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = { + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE, + (EFI_HANDLE) NULL, + { + ConSplitterTextOutReset, + ConSplitterTextOutOutputString, + ConSplitterTextOutTestString, + ConSplitterTextOutQueryMode, + ConSplitterTextOutSetMode, + ConSplitterTextOutSetAttribute, + ConSplitterTextOutClearScreen, + ConSplitterTextOutSetCursorPosition, + ConSplitterTextOutEnableCursor, + (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL + }, + { + 1, + 0, + 0, + 0, + 0, + FALSE, + }, + { + ConSpliterGraphicsOutputQueryMode, + ConSpliterGraphicsOutputSetMode, + ConSpliterGraphicsOutputBlt, + NULL + }, + (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL, + (TEXT_OUT_GOP_MODE *) NULL, + 0, + TRUE, + { + ConSpliterConsoleControlGetMode, + ConSpliterConsoleControlSetMode, + ConSpliterConsoleControlLockStdIn + }, + + 0, + (TEXT_OUT_AND_GOP_DATA *) NULL, + 0, + (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL, + 0, + (INT32 *) NULL, + + EfiConsoleControlScreenText, + 0, + 0, + (CHAR16 *) NULL, + (INT32 *) NULL +}; + +EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding = { + ConSplitterConInDriverBindingSupported, + ConSplitterConInDriverBindingStart, + ConSplitterConInDriverBindingStop, + 0xa, + NULL, + NULL +}; + +EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding = { + ConSplitterSimplePointerDriverBindingSupported, + ConSplitterSimplePointerDriverBindingStart, + ConSplitterSimplePointerDriverBindingStop, + 0xa, + NULL, + NULL +}; + +EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding = { + ConSplitterConOutDriverBindingSupported, + ConSplitterConOutDriverBindingStart, + ConSplitterConOutDriverBindingStop, + 0xa, + NULL, + NULL +}; + +EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding = { + ConSplitterStdErrDriverBindingSupported, + ConSplitterStdErrDriverBindingStart, + ConSplitterStdErrDriverBindingStop, + 0xa, + NULL, + NULL +}; + +/** + The user Entry Point for module ConSplitter. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeConSplitter( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gConSplitterConInDriverBinding, + ImageHandle, + &gConSplitterConInComponentName, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Status = EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gConSplitterSimplePointerDriverBinding, + NULL, + &gConSplitterSimplePointerComponentName, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Status = EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gConSplitterConOutDriverBinding, + NULL, + &gConSplitterConOutComponentName, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Status = EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gConSplitterStdErrDriverBinding, + NULL, + &gConSplitterStdErrComponentName, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + + // + // Call the original Entry Point + // + Status = ConSplitterDriverEntry (ImageHandle, SystemTable); + + return Status; +} + + +EFI_STATUS +EFIAPI +ConSplitterDriverEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Intialize a virtual console device to act as an agrigator of physical console + devices. + +Arguments: + ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) +Returns: + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + + // + // The driver creates virtual handles for ConIn, ConOut, and StdErr. + // The virtual handles will always exist even if no console exist in the + // system. This is need to support hotplug devices like USB. + // + // + // Create virtual device handle for StdErr Splitter + // + Status = ConSplitterTextOutConstructor (&mStdErr); + if (!EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &mStdErr.VirtualHandle, + &gEfiSimpleTextOutProtocolGuid, + &mStdErr.TextOut, + &gEfiPrimaryStandardErrorDeviceGuid, + NULL, + NULL + ); + } + // + // Create virtual device handle for ConIn Splitter + // + Status = ConSplitterTextInConstructor (&mConIn); + if (!EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &mConIn.VirtualHandle, + &gEfiSimpleTextInProtocolGuid, + &mConIn.TextIn, + &gEfiSimplePointerProtocolGuid, + &mConIn.SimplePointer, + &gEfiPrimaryConsoleInDeviceGuid, + NULL, + NULL + ); + if (!EFI_ERROR (Status)) { + // + // Update the EFI System Table with new virtual console + // + gST->ConsoleInHandle = mConIn.VirtualHandle; + gST->ConIn = &mConIn.TextIn; + } + } + // + // Create virtual device handle for ConOut Splitter + // + Status = ConSplitterTextOutConstructor (&mConOut); + if (!EFI_ERROR (Status)) { + // + // In UEFI mode, Graphics Output Protocol is installed on virtual handle. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mConOut.VirtualHandle, + &gEfiSimpleTextOutProtocolGuid, + &mConOut.TextOut, + &gEfiGraphicsOutputProtocolGuid, + &mConOut.GraphicsOutput, + &gEfiConsoleControlProtocolGuid, + &mConOut.ConsoleControl, + &gEfiPrimaryConsoleOutDeviceGuid, + NULL, + NULL + ); + + if (!EFI_ERROR (Status)) { + // + // Update the EFI System Table with new virtual console + // + gST->ConsoleOutHandle = mConOut.VirtualHandle; + gST->ConOut = &mConOut.TextOut; + } + + } + // + // Update the CRC32 in the EFI System Table header + // + gST->Hdr.CRC32 = 0; + gBS->CalculateCrc32 ( + (UINT8 *) &gST->Hdr, + gST->Hdr.HeaderSize, + &gST->Hdr.CRC32 + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +ConSplitterTextInConstructor ( + TEXT_IN_SPLITTER_PRIVATE_DATA *ConInPrivate + ) +/*++ + +Routine Description: + + Construct the ConSplitter. + +Arguments: + + ConInPrivate - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure. + +Returns: + EFI_OUT_OF_RESOURCES - Out of resources. + +--*/ +{ + EFI_STATUS Status; + + // + // Initilize console input splitter's private data. + // + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *), + &ConInPrivate->TextInListCount, + (VOID **) &ConInPrivate->TextInList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Create Event to support locking StdIn Device + // + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + ConSpliterConsoleControlLockStdInEvent, + NULL, + &ConInPrivate->LockEvent + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + ConSplitterTextInWaitForKey, + ConInPrivate, + &ConInPrivate->TextIn.WaitForKey + ); + ASSERT_EFI_ERROR (Status); + + ConInPrivate->SimplePointer.Mode = &ConInPrivate->SimplePointerMode; + + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_POINTER_PROTOCOL *), + &ConInPrivate->PointerListCount, + (VOID **) &ConInPrivate->PointerList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + ConSplitterSimplePointerWaitForInput, + ConInPrivate, + &ConInPrivate->SimplePointer.WaitForInput + ); + + return Status; +} + +EFI_STATUS +ConSplitterTextOutConstructor ( + TEXT_OUT_SPLITTER_PRIVATE_DATA *ConOutPrivate + ) +{ + EFI_STATUS Status; + + // + // Initilize console output splitter's private data. + // + ConOutPrivate->TextOut.Mode = &ConOutPrivate->TextOutMode; + + Status = ConSplitterGrowBuffer ( + sizeof (TEXT_OUT_AND_GOP_DATA), + &ConOutPrivate->TextOutListCount, + (VOID **) &ConOutPrivate->TextOutList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + Status = ConSplitterGrowBuffer ( + sizeof (TEXT_OUT_SPLITTER_QUERY_DATA), + &ConOutPrivate->TextOutQueryDataCount, + (VOID **) &ConOutPrivate->TextOutQueryData + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Setup the DevNullTextOut console to 80 x 25 + // + ConOutPrivate->TextOutQueryData[0].Columns = 80; + ConOutPrivate->TextOutQueryData[0].Rows = 25; + DevNullTextOutSetMode (ConOutPrivate, 0); + + // + // Setup resource for mode information in Graphics Output Protocol interface + // + if ((ConOutPrivate->GraphicsOutput.Mode = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE))) == NULL) { + return EFI_OUT_OF_RESOURCES; + } + if ((ConOutPrivate->GraphicsOutput.Mode->Info = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel + // + if ((ConOutPrivate->GraphicsOutputModeBuffer = AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE))) == NULL) { + return EFI_OUT_OF_RESOURCES; + } + ConOutPrivate->GraphicsOutputModeBuffer[0].HorizontalResolution = 800; + ConOutPrivate->GraphicsOutputModeBuffer[0].VerticalResolution = 600; + + // + // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode() + // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat + // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize + // + ConOutPrivate->GraphicsOutput.Mode->Info->Version = 0; + ConOutPrivate->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly; + ConOutPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + ConOutPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL; + ConOutPrivate->GraphicsOutput.Mode->FrameBufferSize = 0; + + ConOutPrivate->GraphicsOutput.Mode->MaxMode = 1; + // + // Initial current mode to unknow state, and then set to mode 0 + // + ConOutPrivate->GraphicsOutput.Mode->Mode = 0xffff; + ConOutPrivate->GraphicsOutput.SetMode (&ConOutPrivate->GraphicsOutput, 0); + + return Status; +} + +STATIC +EFI_STATUS +ConSplitterSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_GUID *Guid + ) +/*++ + +Routine Description: + Generic Supported Check + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller Handle. + Guid - Guid. + +Returns: + + EFI_UNSUPPORTED - unsupported. + EFI_SUCCESS - operation is OK. + +--*/ +{ + EFI_STATUS Status; + VOID *Instance; + + // + // Make sure the Console Splitter does not attempt to attach to itself + // + if (ControllerHandle == mConIn.VirtualHandle) { + return EFI_UNSUPPORTED; + } + + if (ControllerHandle == mConOut.VirtualHandle) { + return EFI_UNSUPPORTED; + } + + if (ControllerHandle == mStdErr.VirtualHandle) { + return EFI_UNSUPPORTED; + } + // + // Check to see whether the handle has the ConsoleInDevice GUID on it + // + Status = gBS->OpenProtocol ( + ControllerHandle, + Guid, + &Instance, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + ControllerHandle, + Guid, + This->DriverBindingHandle, + ControllerHandle + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Console In Supported Check + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + + EFI_STATUS + +--*/ +{ + return ConSplitterSupported ( + This, + ControllerHandle, + &gEfiConsoleInDeviceGuid + ); +} + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Standard Error Supported Check + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + + EFI_STATUS + +--*/ +{ + return ConSplitterSupported ( + This, + ControllerHandle, + &gEfiSimplePointerProtocolGuid + ); +} + +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Console Out Supported Check + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + + EFI_STATUS + +--*/ +{ + return ConSplitterSupported ( + This, + ControllerHandle, + &gEfiConsoleOutDeviceGuid + ); +} + +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Standard Error Supported Check + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + + EFI_STATUS + +--*/ +{ + return ConSplitterSupported ( + This, + ControllerHandle, + &gEfiStandardErrorDeviceGuid + ); +} + +STATIC +EFI_STATUS +EFIAPI +ConSplitterStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ConSplitterVirtualHandle, + IN EFI_GUID *DeviceGuid, + IN EFI_GUID *InterfaceGuid, + IN VOID **Interface + ) +/*++ + +Routine Description: + Start ConSplitter on ControllerHandle, and create the virtual + agrogated console device on first call Start for a SimpleTextIn handle. + +Arguments: + (Standard DriverBinding Protocol Start() function) + +Returns: + EFI_ERROR if a SimpleTextIn protocol is not started. + +--*/ +{ + EFI_STATUS Status; + VOID *Instance; + + // + // Check to see whether the handle has the ConsoleInDevice GUID on it + // + Status = gBS->OpenProtocol ( + ControllerHandle, + DeviceGuid, + &Instance, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + DeviceGuid, + &Instance, + This->DriverBindingHandle, + ConSplitterVirtualHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return gBS->OpenProtocol ( + ControllerHandle, + InterfaceGuid, + Interface, + This->DriverBindingHandle, + ConSplitterVirtualHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); +} + +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Start ConSplitter on ControllerHandle, and create the virtual + agrogated console device on first call Start for a SimpleTextIn handle. + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + + EFI_STATUS + EFI_ERROR if a SimpleTextIn protocol is not started. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn; + + // + // Start ConSplitter on ControllerHandle, and create the virtual + // agrogated console device on first call Start for a SimpleTextIn handle. + // + Status = ConSplitterStart ( + This, + ControllerHandle, + mConIn.VirtualHandle, + &gEfiConsoleInDeviceGuid, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &TextIn + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return ConSplitterTextInAddDevice (&mConIn, TextIn); +} + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Start ConSplitter on ControllerHandle, and create the virtual + agrogated console device on first call Start for a SimpleTextIn handle. + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + + EFI_ERROR if a SimpleTextIn protocol is not started. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer; + + Status = ConSplitterStart ( + This, + ControllerHandle, + mConIn.VirtualHandle, + &gEfiSimplePointerProtocolGuid, + &gEfiSimplePointerProtocolGuid, + (VOID **) &SimplePointer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return ConSplitterSimplePointerAddDevice (&mConIn, SimplePointer); +} + +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Start ConSplitter on ControllerHandle, and create the virtual + agrogated console device on first call Start for a SimpleTextIn handle. + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + EFI_ERROR if a SimpleTextIn protocol is not started. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + + Status = ConSplitterStart ( + This, + ControllerHandle, + mConOut.VirtualHandle, + &gEfiConsoleOutDeviceGuid, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Try to Open Graphics Output protocol + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &GraphicsOutput, + This->DriverBindingHandle, + mConOut.VirtualHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + GraphicsOutput = NULL; + } + // + // Open UGA_DRAW protocol + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUgaDrawProtocolGuid, + (VOID **) &UgaDraw, + This->DriverBindingHandle, + mConOut.VirtualHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + UgaDraw = NULL; + } + // + // If both ConOut and StdErr incorporate the same Text Out device, + // their MaxMode and QueryData should be the intersection of both. + // + Status = ConSplitterTextOutAddDevice (&mConOut, TextOut, GraphicsOutput, UgaDraw); + ConSplitterTextOutSetAttribute (&mConOut.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + + return Status; +} + +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Start ConSplitter on ControllerHandle, and create the virtual + agrogated console device on first call Start for a SimpleTextIn handle. + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + EFI_ERROR if a SimpleTextIn protocol is not started. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; + + Status = ConSplitterStart ( + This, + ControllerHandle, + mStdErr.VirtualHandle, + &gEfiStandardErrorDeviceGuid, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // If both ConOut and StdErr incorporate the same Text Out device, + // their MaxMode and QueryData should be the intersection of both. + // + Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL, NULL); + ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK)); + if (EFI_ERROR (Status)) { + return Status; + } + + if (mStdErr.CurrentNumberOfConsoles == 1) { + gST->StandardErrorHandle = mStdErr.VirtualHandle; + gST->StdErr = &mStdErr.TextOut; + // + // Update the CRC32 in the EFI System Table header + // + gST->Hdr.CRC32 = 0; + gBS->CalculateCrc32 ( + (UINT8 *) &gST->Hdr, + gST->Hdr.HeaderSize, + &gST->Hdr.CRC32 + ); + } + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +ConSplitterStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ConSplitterVirtualHandle, + IN EFI_GUID *DeviceGuid, + IN EFI_GUID *InterfaceGuid, + IN VOID **Interface + ) +/*++ + +Routine Description: + +Arguments: + (Standard DriverBinding Protocol Stop() function) + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + + Status = gBS->OpenProtocol ( + ControllerHandle, + InterfaceGuid, + Interface, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // close the protocol refered. + // + gBS->CloseProtocol ( + ControllerHandle, + DeviceGuid, + This->DriverBindingHandle, + ConSplitterVirtualHandle + ); + gBS->CloseProtocol ( + ControllerHandle, + DeviceGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + (Standard DriverBinding Protocol Stop() function) + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn; + + if (NumberOfChildren == 0) { + return EFI_SUCCESS; + } + + Status = ConSplitterStop ( + This, + ControllerHandle, + mConIn.VirtualHandle, + &gEfiConsoleInDeviceGuid, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &TextIn + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Delete this console input device's data structures. + // + return ConSplitterTextInDeleteDevice (&mConIn, TextIn); +} + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + (Standard DriverBinding Protocol Stop() function) + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer; + + if (NumberOfChildren == 0) { + return EFI_SUCCESS; + } + + Status = ConSplitterStop ( + This, + ControllerHandle, + mConIn.VirtualHandle, + &gEfiSimplePointerProtocolGuid, + &gEfiSimplePointerProtocolGuid, + (VOID **) &SimplePointer + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Delete this console input device's data structures. + // + return ConSplitterSimplePointerDeleteDevice (&mConIn, SimplePointer); +} + +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + (Standard DriverBinding Protocol Stop() function) + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; + + if (NumberOfChildren == 0) { + return EFI_SUCCESS; + } + + Status = ConSplitterStop ( + This, + ControllerHandle, + mConOut.VirtualHandle, + &gEfiConsoleOutDeviceGuid, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Delete this console output device's data structures. + // + return ConSplitterTextOutDeleteDevice (&mConOut, TextOut); +} + +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + (Standard DriverBinding Protocol Stop() function) + +Returns: + + EFI_SUCCESS - Complete successfully. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; + + if (NumberOfChildren == 0) { + return EFI_SUCCESS; + } + + Status = ConSplitterStop ( + This, + ControllerHandle, + mStdErr.VirtualHandle, + &gEfiStandardErrorDeviceGuid, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Delete this console error out device's data structures. + // + Status = ConSplitterTextOutDeleteDevice (&mStdErr, TextOut); + if (EFI_ERROR (Status)) { + return Status; + } + + if (mStdErr.CurrentNumberOfConsoles == 0) { + gST->StandardErrorHandle = NULL; + gST->StdErr = NULL; + // + // Update the CRC32 in the EFI System Table header + // + gST->Hdr.CRC32 = 0; + gBS->CalculateCrc32 ( + (UINT8 *) &gST->Hdr, + gST->Hdr.HeaderSize, + &gST->Hdr.CRC32 + ); + } + + return Status; +} + +EFI_STATUS +ConSplitterGrowBuffer ( + IN UINTN SizeOfCount, + IN UINTN *Count, + IN OUT VOID **Buffer + ) +/*++ + +Routine Description: + Take the passed in Buffer of size SizeOfCount and grow the buffer + by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount + bytes. Copy the current data in Buffer to the new version of Buffer + and free the old version of buffer. + + +Arguments: + SizeOfCount - Size of element in array + Count - Current number of elements in array + Buffer - Bigger version of passed in Buffer with all the data + +Returns: + EFI_SUCCESS - Buffer size has grown + EFI_OUT_OF_RESOURCES - Could not grow the buffer size + + None + +--*/ +{ + UINTN NewSize; + UINTN OldSize; + VOID *Ptr; + + // + // grow the buffer to new buffer size, + // copy the old buffer's content to the new-size buffer, + // then free the old buffer. + // + OldSize = *Count * SizeOfCount; + *Count += CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT; + NewSize = *Count * SizeOfCount; + + Ptr = AllocateZeroPool (NewSize); + if (Ptr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (Ptr, *Buffer, OldSize); + + if (*Buffer != NULL) { + FreePool (*Buffer); + } + + *Buffer = Ptr; + + return EFI_SUCCESS; +} + +EFI_STATUS +ConSplitterTextInAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + EFI_SUCCESS + EFI_OUT_OF_RESOURCES + +--*/ +{ + EFI_STATUS Status; + + // + // If the Text In List is full, enlarge it by calling growbuffer(). + // + if (Private->CurrentNumberOfConsoles >= Private->TextInListCount) { + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *), + &Private->TextInListCount, + (VOID **) &Private->TextInList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + // + // Add the new text-in device data structure into the Text In List. + // + Private->TextInList[Private->CurrentNumberOfConsoles] = TextIn; + Private->CurrentNumberOfConsoles++; + + // + // Extra CheckEvent added to reduce the double CheckEvent() in UI.c + // + gBS->CheckEvent (TextIn->WaitForKey); + + return EFI_SUCCESS; +} + +EFI_STATUS +ConSplitterTextInDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + +--*/ +{ + UINTN Index; + // + // Remove the specified text-in device data structure from the Text In List, + // and rearrange the remaining data structures in the Text In List. + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + if (Private->TextInList[Index] == TextIn) { + for (Index = Index; Index < Private->CurrentNumberOfConsoles - 1; Index++) { + Private->TextInList[Index] = Private->TextInList[Index + 1]; + } + + Private->CurrentNumberOfConsoles--; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +ConSplitterSimplePointerAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + EFI_OUT_OF_RESOURCES + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + + // + // If the Text In List is full, enlarge it by calling growbuffer(). + // + if (Private->CurrentNumberOfPointers >= Private->PointerListCount) { + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_POINTER_PROTOCOL *), + &Private->PointerListCount, + (VOID **) &Private->PointerList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + // + // Add the new text-in device data structure into the Text In List. + // + Private->PointerList[Private->CurrentNumberOfPointers] = SimplePointer; + Private->CurrentNumberOfPointers++; + return EFI_SUCCESS; +} + +EFI_STATUS +ConSplitterSimplePointerDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + UINTN Index; + // + // Remove the specified text-in device data structure from the Text In List, + // and rearrange the remaining data structures in the Text In List. + // + for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) { + if (Private->PointerList[Index] == SimplePointer) { + for (Index = Index; Index < Private->CurrentNumberOfPointers - 1; Index++) { + Private->PointerList[Index] = Private->PointerList[Index + 1]; + } + + Private->CurrentNumberOfPointers--; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +STATIC +EFI_STATUS +ConSplitterGrowMapTable ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + UINTN Size; + UINTN NewSize; + UINTN TotalSize; + INT32 *TextOutModeMap; + INT32 *OldTextOutModeMap; + INT32 *SrcAddress; + INT32 Index; + + NewSize = Private->TextOutListCount * sizeof (INT32); + OldTextOutModeMap = Private->TextOutModeMap; + TotalSize = NewSize * Private->TextOutQueryDataCount; + + TextOutModeMap = AllocateZeroPool (TotalSize); + if (TextOutModeMap == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SetMem (TextOutModeMap, TotalSize, 0xFF); + Private->TextOutModeMap = TextOutModeMap; + + // + // If TextOutList has been enlarged, need to realloc the mode map table + // The mode map table is regarded as a two dimension array. + // + // Old New + // 0 ---------> TextOutListCount ----> TextOutListCount + // | ------------------------------------------- + // | | | | + // | | | | + // | | | | + // | | | | + // | | | | + // \/ | | | + // ------------------------------------------- + // QueryDataCount + // + if (OldTextOutModeMap != NULL) { + + Size = Private->CurrentNumberOfConsoles * sizeof (INT32); + Index = 0; + SrcAddress = OldTextOutModeMap; + + // + // Copy the old data to the new one + // + while (Index < Private->TextOutMode.MaxMode) { + CopyMem (TextOutModeMap, SrcAddress, Size); + TextOutModeMap += NewSize; + SrcAddress += Size; + Index++; + } + // + // Free the old buffer + // + FreePool (OldTextOutModeMap); + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ConSplitterAddOutputMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + INT32 MaxMode; + INT32 Mode; + UINTN Index; + + MaxMode = TextOut->Mode->MaxMode; + Private->TextOutMode.MaxMode = MaxMode; + + // + // Grow the buffer if query data buffer is not large enough to + // hold all the mode supported by the first console. + // + while (MaxMode > (INT32) Private->TextOutQueryDataCount) { + Status = ConSplitterGrowBuffer ( + sizeof (TEXT_OUT_SPLITTER_QUERY_DATA), + &Private->TextOutQueryDataCount, + (VOID **) &Private->TextOutQueryData + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + // + // Allocate buffer for the output mode map + // + Status = ConSplitterGrowMapTable (Private); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // As the first textout device, directly add the mode in to QueryData + // and at the same time record the mapping between QueryData and TextOut. + // + Mode = 0; + Index = 0; + while (Mode < MaxMode) { + TextOut->QueryMode ( + TextOut, + Mode, + &Private->TextOutQueryData[Mode].Columns, + &Private->TextOutQueryData[Mode].Rows + ); + Private->TextOutModeMap[Index] = Mode; + Mode++; + Index += Private->TextOutListCount; + } + + return EFI_SUCCESS; +} + +STATIC +VOID +ConSplitterGetIntersection ( + IN INT32 *TextOutModeMap, + IN INT32 *NewlyAddedMap, + IN UINTN MapStepSize, + IN UINTN NewMapStepSize, + OUT INT32 *MaxMode, + OUT INT32 *CurrentMode + ) +{ + INT32 Index; + INT32 *CurrentMapEntry; + INT32 *NextMapEntry; + INT32 CurrentMaxMode; + INT32 Mode; + + Index = 0; + CurrentMapEntry = TextOutModeMap; + NextMapEntry = TextOutModeMap; + CurrentMaxMode = *MaxMode; + Mode = *CurrentMode; + + while (Index < CurrentMaxMode) { + if (*NewlyAddedMap == -1) { + // + // This mode is not supported any more. Remove it. Special care + // must be taken as this remove will also affect current mode; + // + if (Index == *CurrentMode) { + Mode = -1; + } else if (Index < *CurrentMode) { + Mode--; + } + (*MaxMode)--; + } else { + if (CurrentMapEntry != NextMapEntry) { + CopyMem (NextMapEntry, CurrentMapEntry, MapStepSize * sizeof (INT32)); + } + + NextMapEntry += MapStepSize; + } + + CurrentMapEntry += MapStepSize; + NewlyAddedMap += NewMapStepSize; + Index++; + } + + *CurrentMode = Mode; + + return ; +} + +STATIC +VOID +ConSplitterSyncOutputMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut + ) +/*++ + +Routine Description: + +Arguments: + Private - Private data structure. + TextOut - Text Out Protocol. +Returns: + + None + +--*/ +{ + INT32 CurrentMaxMode; + INT32 Mode; + INT32 Index; + INT32 *TextOutModeMap; + INT32 *MapTable; + TEXT_OUT_SPLITTER_QUERY_DATA *TextOutQueryData; + UINTN Rows; + UINTN Columns; + UINTN StepSize; + + // + // Must make sure that current mode won't change even if mode number changes + // + CurrentMaxMode = Private->TextOutMode.MaxMode; + TextOutModeMap = Private->TextOutModeMap; + StepSize = Private->TextOutListCount; + TextOutQueryData = Private->TextOutQueryData; + + // + // Query all the mode that the newly added TextOut supports + // + Mode = 0; + MapTable = TextOutModeMap + Private->CurrentNumberOfConsoles; + while (Mode < TextOut->Mode->MaxMode) { + TextOut->QueryMode (TextOut, Mode, &Columns, &Rows); + + // + // Search the QueryData database to see if they intersects + // + Index = 0; + while (Index < CurrentMaxMode) { + if ((TextOutQueryData[Index].Rows == Rows) && (TextOutQueryData[Index].Columns == Columns)) { + MapTable[Index * StepSize] = Mode; + break; + } + + Index++; + } + + Mode++; + } + // + // Now search the TextOutModeMap table to find the intersection of supported + // mode between ConSplitter and the newly added device. + // + ConSplitterGetIntersection ( + TextOutModeMap, + MapTable, + StepSize, + StepSize, + &Private->TextOutMode.MaxMode, + &Private->TextOutMode.Mode + ); + + return ; +} + +STATIC +EFI_STATUS +ConSplitterGetIntersectionBetweenConOutAndStrErr ( + VOID + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + EFI_OUT_OF_RESOURCES + +--*/ +{ + UINTN ConOutNumOfConsoles; + UINTN StdErrNumOfConsoles; + TEXT_OUT_AND_GOP_DATA *ConOutTextOutList; + TEXT_OUT_AND_GOP_DATA *StdErrTextOutList; + UINTN Indexi; + UINTN Indexj; + UINTN Rows; + UINTN Columns; + INT32 ConOutMaxMode; + INT32 StdErrMaxMode; + INT32 Mode; + INT32 Index; + INT32 *ConOutModeMap; + INT32 *StdErrModeMap; + INT32 *ConOutMapTable; + INT32 *StdErrMapTable; + TEXT_OUT_SPLITTER_QUERY_DATA *ConOutQueryData; + TEXT_OUT_SPLITTER_QUERY_DATA *StdErrQueryData; + BOOLEAN FoundTheSameTextOut; + UINTN ConOutMapTableSize; + UINTN StdErrMapTableSize; + + ConOutNumOfConsoles = mConOut.CurrentNumberOfConsoles; + StdErrNumOfConsoles = mStdErr.CurrentNumberOfConsoles; + ConOutTextOutList = mConOut.TextOutList; + StdErrTextOutList = mStdErr.TextOutList; + + Indexi = 0; + FoundTheSameTextOut = FALSE; + while ((Indexi < ConOutNumOfConsoles) && (!FoundTheSameTextOut)) { + Indexj = 0; + while (Indexj < StdErrNumOfConsoles) { + if (ConOutTextOutList->TextOut == StdErrTextOutList->TextOut) { + FoundTheSameTextOut = TRUE; + break; + } + + Indexj++; + StdErrTextOutList++; + } + + Indexi++; + ConOutTextOutList++; + } + + if (!FoundTheSameTextOut) { + return EFI_SUCCESS; + } + // + // Must make sure that current mode won't change even if mode number changes + // + ConOutMaxMode = mConOut.TextOutMode.MaxMode; + ConOutModeMap = mConOut.TextOutModeMap; + ConOutQueryData = mConOut.TextOutQueryData; + + StdErrMaxMode = mStdErr.TextOutMode.MaxMode; + StdErrModeMap = mStdErr.TextOutModeMap; + StdErrQueryData = mStdErr.TextOutQueryData; + + // + // Allocate the map table and set the map table's index to -1. + // + ConOutMapTableSize = ConOutMaxMode * sizeof (INT32); + ConOutMapTable = AllocateZeroPool (ConOutMapTableSize); + if (ConOutMapTable == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SetMem (ConOutMapTable, ConOutMapTableSize, 0xFF); + + StdErrMapTableSize = StdErrMaxMode * sizeof (INT32); + StdErrMapTable = AllocateZeroPool (StdErrMapTableSize); + if (StdErrMapTable == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SetMem (StdErrMapTable, StdErrMapTableSize, 0xFF); + + // + // Find the intersection of the two set of modes. If they actually intersect, the + // correponding entry in the map table is set to 1. + // + Mode = 0; + while (Mode < ConOutMaxMode) { + // + // Search the other's QueryData database to see if they intersect + // + Index = 0; + Rows = ConOutQueryData[Mode].Rows; + Columns = ConOutQueryData[Mode].Columns; + while (Index < StdErrMaxMode) { + if ((StdErrQueryData[Index].Rows == Rows) && (StdErrQueryData[Index].Columns == Columns)) { + ConOutMapTable[Mode] = 1; + StdErrMapTable[Index] = 1; + break; + } + + Index++; + } + + Mode++; + } + // + // Now search the TextOutModeMap table to find the intersection of supported + // mode between ConSplitter and the newly added device. + // + ConSplitterGetIntersection ( + ConOutModeMap, + ConOutMapTable, + mConOut.TextOutListCount, + 1, + &(mConOut.TextOutMode.MaxMode), + &(mConOut.TextOutMode.Mode) + ); + if (mConOut.TextOutMode.Mode < 0) { + mConOut.TextOut.SetMode (&(mConOut.TextOut), 0); + } + + ConSplitterGetIntersection ( + StdErrModeMap, + StdErrMapTable, + mStdErr.TextOutListCount, + 1, + &(mStdErr.TextOutMode.MaxMode), + &(mStdErr.TextOutMode.Mode) + ); + if (mStdErr.TextOutMode.Mode < 0) { + mStdErr.TextOut.SetMode (&(mStdErr.TextOut), 0); + } + + FreePool (ConOutMapTable); + FreePool (StdErrMapTable); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ConSplitterAddGraphicsOutputMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput, + IN EFI_UGA_DRAW_PROTOCOL *UgaDraw + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + TEXT_OUT_GOP_MODE *Mode; + UINTN SizeOfInfo; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *CurrentGraphicsOutputMode; + TEXT_OUT_GOP_MODE *ModeBuffer; + TEXT_OUT_GOP_MODE *MatchedMode; + UINTN NumberIndex; + BOOLEAN Match; + + if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) { + return EFI_UNSUPPORTED; + } + + CurrentGraphicsOutputMode = Private->GraphicsOutput.Mode; + + if (GraphicsOutput != NULL) { + if (Private->CurrentNumberOfGraphicsOutput == 0) { + // + // This is the first Graphics Output device added + // + CurrentGraphicsOutputMode->MaxMode = GraphicsOutput->Mode->MaxMode; + CurrentGraphicsOutputMode->Mode = GraphicsOutput->Mode->Mode; + CopyMem (CurrentGraphicsOutputMode->Info, GraphicsOutput->Mode->Info, GraphicsOutput->Mode->SizeOfInfo); + CurrentGraphicsOutputMode->SizeOfInfo = GraphicsOutput->Mode->SizeOfInfo; + CurrentGraphicsOutputMode->FrameBufferBase = GraphicsOutput->Mode->FrameBufferBase; + CurrentGraphicsOutputMode->FrameBufferSize = GraphicsOutput->Mode->FrameBufferSize; + + // + // Allocate resource for the private mode buffer + // + ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * GraphicsOutput->Mode->MaxMode); + if (ModeBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + FreePool (Private->GraphicsOutputModeBuffer); + Private->GraphicsOutputModeBuffer = ModeBuffer; + + // + // Store all supported display modes to the private mode buffer + // + Mode = ModeBuffer; + for (Index = 0; Index < GraphicsOutput->Mode->MaxMode; Index++) { + Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) Index, &SizeOfInfo, &Info); + if (EFI_ERROR (Status)) { + return Status; + } + Mode->HorizontalResolution = Info->HorizontalResolution; + Mode->VerticalResolution = Info->VerticalResolution; + Mode++; + FreePool (Info); + } + } else { + // + // Check intersection of display mode + // + ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * CurrentGraphicsOutputMode->MaxMode); + if (ModeBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + MatchedMode = ModeBuffer; + Mode = &Private->GraphicsOutputModeBuffer[0]; + for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) { + Match = FALSE; + + for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex++) { + Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info); + if (EFI_ERROR (Status)) { + return Status; + } + if ((Info->HorizontalResolution == Mode->HorizontalResolution) && + (Info->VerticalResolution == Mode->VerticalResolution)){ + Match = TRUE; + FreePool (Info); + break; + } + FreePool (Info); + } + + if (Match) { + CopyMem (MatchedMode, Mode, sizeof (TEXT_OUT_GOP_MODE)); + MatchedMode++; + } + + Mode++; + } + + // + // Drop the old mode buffer, assign it to a new one + // + FreePool (Private->GraphicsOutputModeBuffer); + Private->GraphicsOutputModeBuffer = ModeBuffer; + + // + // Physical frame buffer is no longer available when there are more than one physical GOP devices + // + CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (TEXT_OUT_GOP_MODE)); + CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly; + ZeroMem (&CurrentGraphicsOutputMode->Info->PixelInformation, sizeof (EFI_PIXEL_BITMASK)); + CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL; + CurrentGraphicsOutputMode->FrameBufferSize = 0; + } + + // + // Select a prefered Display mode 800x600 + // + for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) { + Mode = &Private->GraphicsOutputModeBuffer[Index]; + if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) { + break; + } + } + // + // Prefered mode is not found, set to mode 0 + // + if (Index >= CurrentGraphicsOutputMode->MaxMode) { + Index = 0; + } + + // + // Current mode number may need update now, so set it to an invalide mode number + // + CurrentGraphicsOutputMode->Mode = 0xffff; + } else { + // + // For UGA device, it's inconvenient to retrieve all the supported display modes. + // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec + // + CurrentGraphicsOutputMode->MaxMode = 1; + CurrentGraphicsOutputMode->Info->Version = 0; + CurrentGraphicsOutputMode->Info->HorizontalResolution = 800; + CurrentGraphicsOutputMode->Info->VerticalResolution = 600; + CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly; + CurrentGraphicsOutputMode->Info->PixelsPerScanLine = 800; + CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL; + CurrentGraphicsOutputMode->FrameBufferSize = 0; + + // + // Update the private mode buffer + // + ModeBuffer = &Private->GraphicsOutputModeBuffer[0]; + ModeBuffer->HorizontalResolution = 800; + ModeBuffer->VerticalResolution = 600; + + // + // Current mode is unknow now, set it to an invalid mode number 0xffff + // + CurrentGraphicsOutputMode->Mode = 0xffff; + Index = 0; + } + + // + // Force GraphicsOutput mode to be set, + // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode + // + Private->HardwareNeedsStarting = TRUE; + Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) Index); + + Private->CurrentNumberOfGraphicsOutput++; + + return Status; +} + +EFI_STATUS +ConSplitterTextOutAddDevice ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut, + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput, + IN EFI_UGA_DRAW_PROTOCOL *UgaDraw + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + UINTN CurrentNumOfConsoles; + INT32 CurrentMode; + INT32 MaxMode; + TEXT_OUT_AND_GOP_DATA *TextAndGop; + + Status = EFI_SUCCESS; + CurrentNumOfConsoles = Private->CurrentNumberOfConsoles; + + // + // If the Text Out List is full, enlarge it by calling growbuffer(). + // + while (CurrentNumOfConsoles >= Private->TextOutListCount) { + Status = ConSplitterGrowBuffer ( + sizeof (TEXT_OUT_AND_GOP_DATA), + &Private->TextOutListCount, + (VOID **) &Private->TextOutList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Also need to reallocate the TextOutModeMap table + // + Status = ConSplitterGrowMapTable (Private); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + + TextAndGop = &Private->TextOutList[CurrentNumOfConsoles]; + + TextAndGop->TextOut = TextOut; + TextAndGop->GraphicsOutput = GraphicsOutput; + TextAndGop->UgaDraw = UgaDraw; + + if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) { + // + // If No UGA device then use the ConOut device + // + TextAndGop->TextOutEnabled = TRUE; + } else { + // + // If UGA device use ConOut device only used if UGA screen is in Text mode + // + TextAndGop->TextOutEnabled = (BOOLEAN) (Private->ConsoleOutputMode == EfiConsoleControlScreenText); + } + + if (CurrentNumOfConsoles == 0) { + // + // Add the first device's output mode to console splitter's mode list + // + Status = ConSplitterAddOutputMode (Private, TextOut); + } else { + ConSplitterSyncOutputMode (Private, TextOut); + } + + Private->CurrentNumberOfConsoles++; + + // + // Scan both TextOutList, for the intersection TextOut device + // maybe both ConOut and StdErr incorporate the same Text Out + // device in them, thus the output of both should be synced. + // + ConSplitterGetIntersectionBetweenConOutAndStrErr (); + + CurrentMode = Private->TextOutMode.Mode; + MaxMode = Private->TextOutMode.MaxMode; + ASSERT (MaxMode >= 1); + + if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) { + ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw); + } + + if (Private->ConsoleOutputMode == EfiConsoleControlScreenGraphics && GraphicsOutput != NULL) { + // + // We just added a new UGA device in graphics mode + // + DevNullGopSync (Private, GraphicsOutput, UgaDraw); + } else if ((CurrentMode >= 0) && ((GraphicsOutput != NULL) || (UgaDraw != NULL)) && (CurrentMode < Private->TextOutMode.MaxMode)) { + // + // The new console supports the same mode of the current console so sync up + // + DevNullSyncGopStdOut (Private); + } else { + // + // If ConOut, then set the mode to Mode #0 which us 80 x 25 + // + Private->TextOut.SetMode (&Private->TextOut, 0); + } + + return Status; +} + +EFI_STATUS +ConSplitterTextOutDeleteDevice ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + INT32 Index; + UINTN CurrentNumOfConsoles; + TEXT_OUT_AND_GOP_DATA *TextOutList; + EFI_STATUS Status; + + // + // Remove the specified text-out device data structure from the Text out List, + // and rearrange the remaining data structures in the Text out List. + // + CurrentNumOfConsoles = Private->CurrentNumberOfConsoles; + Index = (INT32) CurrentNumOfConsoles - 1; + TextOutList = Private->TextOutList; + while (Index >= 0) { + if (TextOutList->TextOut == TextOut) { + CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index); + CurrentNumOfConsoles--; + break; + } + + Index--; + TextOutList++; + } + // + // The specified TextOut is not managed by the ConSplitter driver + // + if (Index < 0) { + return EFI_NOT_FOUND; + } + + if (CurrentNumOfConsoles == 0) { + // + // If the number of consoles is zero clear the Dev NULL device + // + Private->CurrentNumberOfConsoles = 0; + Private->TextOutMode.MaxMode = 1; + Private->TextOutQueryData[0].Columns = 80; + Private->TextOutQueryData[0].Rows = 25; + DevNullTextOutSetMode (Private, 0); + + return EFI_SUCCESS; + } + // + // Max Mode is realy an intersection of the QueryMode command to all + // devices. So we must copy the QueryMode of the first device to + // QueryData. + // + ZeroMem ( + Private->TextOutQueryData, + Private->TextOutQueryDataCount * sizeof (TEXT_OUT_SPLITTER_QUERY_DATA) + ); + + FreePool (Private->TextOutModeMap); + Private->TextOutModeMap = NULL; + TextOutList = Private->TextOutList; + + // + // Add the first TextOut to the QueryData array and ModeMap table + // + Status = ConSplitterAddOutputMode (Private, TextOutList->TextOut); + + // + // Now add one by one + // + Index = 1; + Private->CurrentNumberOfConsoles = 1; + TextOutList++; + while ((UINTN) Index < CurrentNumOfConsoles) { + ConSplitterSyncOutputMode (Private, TextOutList->TextOut); + Index++; + Private->CurrentNumberOfConsoles++; + TextOutList++; + } + + ConSplitterGetIntersectionBetweenConOutAndStrErr (); + + return Status; +} +// +// ConSplitter TextIn member functions +// +EFI_STATUS +EFIAPI +ConSplitterTextInReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset the input device and optionaly run diagnostics + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - Driver may perform diagnostics on reset. + + Returns: + EFI_SUCCESS - The device was reset. + EFI_DEVICE_ERROR - The device is not functioning properly and could + not be reset. + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + Private->KeyEventSignalState = FALSE; + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = Private->TextInList[Index]->Reset ( + Private->TextInList[Index], + ExtendedVerification + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextInPrivateReadKeyStroke ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + OUT EFI_INPUT_KEY *Key + ) +/*++ + + Routine Description: + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + Arguments: + This - Protocol instance pointer. + Key - Driver may perform diagnostics on reset. + + Returns: + EFI_SUCCESS - The keystroke information was returned. + EFI_NOT_READY - There was no keystroke data availiable. + EFI_DEVICE_ERROR - The keydtroke information was not returned due to + hardware errors. + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + EFI_INPUT_KEY CurrentKey; + + Key->UnicodeChar = 0; + Key->ScanCode = SCAN_NULL; + + // + // if no physical console input device exists, return EFI_NOT_READY; + // if any physical console input device has key input, + // return the key and EFI_SUCCESS. + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = Private->TextInList[Index]->ReadKeyStroke ( + Private->TextInList[Index], + &CurrentKey + ); + if (!EFI_ERROR (Status)) { + *Key = CurrentKey; + return Status; + } + } + + return EFI_NOT_READY; +} + +BOOLEAN +ConSpliterConssoleControlStdInLocked ( + VOID + ) +/*++ + +Routine Description: + Return TRUE if StdIn is locked. The ConIn device on the virtual handle is + the only device locked. + +Arguments: + NONE + +Returns: + TRUE - StdIn locked + FALSE - StdIn working normally + +--*/ +{ + return mConIn.PasswordEnabled; +} + +VOID +EFIAPI +ConSpliterConsoleControlLockStdInEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + This timer event will fire when StdIn is locked. It will check the key + sequence on StdIn to see if it matches the password. Any error in the + password will cause the check to reset. As long a mConIn.PasswordEnabled is + TRUE the StdIn splitter will not report any input. + +Arguments: + (Standard EFI_EVENT_NOTIFY) + +Returns: + None + +--*/ +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + CHAR16 BackSpaceString[2]; + CHAR16 SpaceString[2]; + + do { + Status = ConSplitterTextInPrivateReadKeyStroke (&mConIn, &Key); + if (!EFI_ERROR (Status)) { + // + // if it's an ENTER, match password + // + if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN) && (Key.ScanCode == SCAN_NULL)) { + mConIn.PwdAttempt[mConIn.PwdIndex] = CHAR_NULL; + if (StrCmp (mConIn.Password, mConIn.PwdAttempt)) { + // + // Password not match + // + ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\rPassword not correct\n\r"); + mConIn.PwdIndex = 0; + } else { + // + // Key matches password sequence + // + gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, 0); + mConIn.PasswordEnabled = FALSE; + Status = EFI_NOT_READY; + } + } else if ((Key.UnicodeChar == CHAR_BACKSPACE) && (Key.ScanCode == SCAN_NULL)) { + // + // BackSpace met + // + if (mConIn.PwdIndex > 0) { + BackSpaceString[0] = CHAR_BACKSPACE; + BackSpaceString[1] = 0; + + SpaceString[0] = ' '; + SpaceString[1] = 0; + + ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString); + ConSplitterTextOutOutputString (&mConOut.TextOut, SpaceString); + ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString); + + mConIn.PwdIndex--; + } + } else if ((Key.ScanCode == SCAN_NULL) && (Key.UnicodeChar >= 32)) { + // + // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input + // + if (mConIn.PwdIndex < (MAX_STD_IN_PASSWORD - 1)) { + if (mConIn.PwdIndex == 0) { + ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\r"); + } + + ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"*"); + mConIn.PwdAttempt[mConIn.PwdIndex] = Key.UnicodeChar; + mConIn.PwdIndex++; + } + } + } + } while (!EFI_ERROR (Status)); +} + +EFI_STATUS +EFIAPI +ConSpliterConsoleControlLockStdIn ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN CHAR16 *Password + ) +/*++ + +Routine Description: + If Password is NULL unlock the password state variable and set the event + timer. If the Password is too big return an error. If the Password is valid + Copy the Password and enable state variable and then arm the periodic timer + +Arguments: + +Returns: + EFI_SUCCESS - Lock the StdIn device + EFI_INVALID_PARAMETER - Password is NULL + EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails + +--*/ +{ + if (Password == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (StrLen (Password) >= MAX_STD_IN_PASSWORD) { + // + // Currently have a max password size + // + return EFI_OUT_OF_RESOURCES; + } + // + // Save the password, initialize state variables and arm event timer + // + StrCpy (mConIn.Password, Password); + mConIn.PasswordEnabled = TRUE; + mConIn.PwdIndex = 0; + gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, (10000 * 25)); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConSplitterTextInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +/*++ + + Routine Description: + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + If the ConIn is password locked make it look like no keystroke is availible + + Arguments: + This - Protocol instance pointer. + Key - Driver may perform diagnostics on reset. + + Returns: + EFI_SUCCESS - The keystroke information was returned. + EFI_NOT_READY - There was no keystroke data availiable. + EFI_DEVICE_ERROR - The keydtroke information was not returned due to + hardware errors. + +--*/ +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + + Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + if (Private->PasswordEnabled) { + // + // If StdIn Locked return not ready + // + return EFI_NOT_READY; + } + + Private->KeyEventSignalState = FALSE; + + return ConSplitterTextInPrivateReadKeyStroke (Private, Key); +} + +VOID +EFIAPI +ConSplitterTextInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + This event agregates all the events of the ConIn devices in the spliter. + If the ConIn is password locked then return. + If any events of physical ConIn devices are signaled, signal the ConIn + spliter event. This will cause the calling code to call + ConSplitterTextInReadKeyStroke (). + +Arguments: + Event - The Event assoicated with callback. + Context - Context registered when Event was created. + +Returns: + None + +--*/ +{ + EFI_STATUS Status; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context; + if (Private->PasswordEnabled) { + // + // If StdIn Locked return not ready + // + return ; + } + + // + // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke() + // + if (Private->KeyEventSignalState) { + gBS->SignalEvent (Event); + return ; + } + // + // if any physical console input device has key input, signal the event. + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = gBS->CheckEvent (Private->TextInList[Index]->WaitForKey); + if (!EFI_ERROR (Status)) { + gBS->SignalEvent (Event); + Private->KeyEventSignalState = TRUE; + } + } +} + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerReset ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset the input device and optionaly run diagnostics + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - Driver may perform diagnostics on reset. + + Returns: + EFI_SUCCESS - The device was reset. + EFI_DEVICE_ERROR - The device is not functioning properly and could + not be reset. + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This); + + Private->InputEventSignalState = FALSE; + + if (Private->CurrentNumberOfPointers == 0) { + return EFI_SUCCESS; + } + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfPointers; Index++) { + Status = Private->PointerList[Index]->Reset ( + Private->PointerList[Index], + ExtendedVerification + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + return ReturnStatus; +} + +STATIC +EFI_STATUS +EFIAPI +ConSplitterSimplePointerPrivateGetState ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN OUT EFI_SIMPLE_POINTER_STATE *State + ) +/*++ + + Routine Description: + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + Arguments: + This - Protocol instance pointer. + State - + + Returns: + EFI_SUCCESS - The keystroke information was returned. + EFI_NOT_READY - There was no keystroke data availiable. + EFI_DEVICE_ERROR - The keydtroke information was not returned due to + hardware errors. + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + UINTN Index; + EFI_SIMPLE_POINTER_STATE CurrentState; + + State->RelativeMovementX = 0; + State->RelativeMovementY = 0; + State->RelativeMovementZ = 0; + State->LeftButton = FALSE; + State->RightButton = FALSE; + + // + // if no physical console input device exists, return EFI_NOT_READY; + // if any physical console input device has key input, + // return the key and EFI_SUCCESS. + // + ReturnStatus = EFI_NOT_READY; + for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) { + + Status = Private->PointerList[Index]->GetState ( + Private->PointerList[Index], + &CurrentState + ); + if (!EFI_ERROR (Status)) { + if (ReturnStatus == EFI_NOT_READY) { + ReturnStatus = EFI_SUCCESS; + } + + if (CurrentState.LeftButton) { + State->LeftButton = TRUE; + } + + if (CurrentState.RightButton) { + State->RightButton = TRUE; + } + + if (CurrentState.RelativeMovementX != 0 && Private->PointerList[Index]->Mode->ResolutionX != 0) { + State->RelativeMovementX += (CurrentState.RelativeMovementX * (INT32) Private->SimplePointerMode.ResolutionX) / (INT32) Private->PointerList[Index]->Mode->ResolutionX; + } + + if (CurrentState.RelativeMovementY != 0 && Private->PointerList[Index]->Mode->ResolutionY != 0) { + State->RelativeMovementY += (CurrentState.RelativeMovementY * (INT32) Private->SimplePointerMode.ResolutionY) / (INT32) Private->PointerList[Index]->Mode->ResolutionY; + } + + if (CurrentState.RelativeMovementZ != 0 && Private->PointerList[Index]->Mode->ResolutionZ != 0) { + State->RelativeMovementZ += (CurrentState.RelativeMovementZ * (INT32) Private->SimplePointerMode.ResolutionZ) / (INT32) Private->PointerList[Index]->Mode->ResolutionZ; + } + } else if (Status == EFI_DEVICE_ERROR) { + ReturnStatus = EFI_DEVICE_ERROR; + } + } + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerGetState ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN OUT EFI_SIMPLE_POINTER_STATE *State + ) +/*++ + + Routine Description: + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + If the ConIn is password locked make it look like no keystroke is availible + + Arguments: + This - Protocol instance pointer. + State - + + Returns: + EFI_SUCCESS - The keystroke information was returned. + EFI_NOT_READY - There was no keystroke data availiable. + EFI_DEVICE_ERROR - The keydtroke information was not returned due to + hardware errors. + +--*/ +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + + Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This); + if (Private->PasswordEnabled) { + // + // If StdIn Locked return not ready + // + return EFI_NOT_READY; + } + + Private->InputEventSignalState = FALSE; + + return ConSplitterSimplePointerPrivateGetState (Private, State); +} + +VOID +EFIAPI +ConSplitterSimplePointerWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + This event agregates all the events of the ConIn devices in the spliter. + If the ConIn is password locked then return. + If any events of physical ConIn devices are signaled, signal the ConIn + spliter event. This will cause the calling code to call + ConSplitterTextInReadKeyStroke (). + +Arguments: + Event - The Event assoicated with callback. + Context - Context registered when Event was created. + +Returns: + None + +--*/ +{ + EFI_STATUS Status; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context; + if (Private->PasswordEnabled) { + // + // If StdIn Locked return not ready + // + return ; + } + + // + // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke() + // + if (Private->InputEventSignalState) { + gBS->SignalEvent (Event); + return ; + } + // + // if any physical console input device has key input, signal the event. + // + for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) { + Status = gBS->CheckEvent (Private->PointerList[Index]->WaitForInput); + if (!EFI_ERROR (Status)) { + gBS->SignalEvent (Event); + Private->InputEventSignalState = TRUE; + } + } +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset the text output device hardware and optionaly run diagnostics + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - Driver may perform more exhaustive verfication + operation of the device during reset. + + Returns: + EFI_SUCCESS - The text output device was reset. + EFI_DEVICE_ERROR - The text output device is not functioning correctly and + could not be reset. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + + if (Private->TextOutList[Index].TextOutEnabled) { + + Status = Private->TextOutList[Index].TextOut->Reset ( + Private->TextOutList[Index].TextOut, + ExtendedVerification + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)); + + Status = DevNullTextOutSetMode (Private, 0); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + + Routine Description: + Write a Unicode string to the output device. + + Arguments: + This - Protocol instance pointer. + String - The NULL-terminated Unicode string to be displayed on the output + device(s). All output devices must also support the Unicode + drawing defined in this file. + + Returns: + EFI_SUCCESS - The string was output to the device. + EFI_DEVICE_ERROR - The device reported an error while attempting to output + the text. + EFI_UNSUPPORTED - The output device's mode is not currently in a + defined text mode. + EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the + characters in the Unicode string could not be + rendered and were skipped. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + UINTN BackSpaceCount; + EFI_STATUS ReturnStatus; + CHAR16 *TargetString; + + This->SetAttribute (This, This->Mode->Attribute); + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + BackSpaceCount = 0; + for (TargetString = WString; *TargetString; TargetString++) { + if (*TargetString == CHAR_BACKSPACE) { + BackSpaceCount++; + } + + } + + if (BackSpaceCount == 0) { + TargetString = WString; + } else { + TargetString = AllocatePool (sizeof (CHAR16) * (StrLen (WString) + BackSpaceCount + 1)); + StrCpy (TargetString, WString); + } + // + // return the worst status met + // + Status = DevNullTextOutOutputString (Private, TargetString); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + + if (Private->TextOutList[Index].TextOutEnabled) { + Status = Private->TextOutList[Index].TextOut->OutputString ( + Private->TextOutList[Index].TextOut, + TargetString + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + if (BackSpaceCount) { + FreePool (TargetString); + } + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + + Routine Description: + Verifies that all characters in a Unicode string can be output to the + target device. + + Arguments: + This - Protocol instance pointer. + String - The NULL-terminated Unicode string to be examined for the output + device(s). + + Returns: + EFI_SUCCESS - The device(s) are capable of rendering the output string. + EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be + rendered by one or more of the output devices mapped + by the EFI handle. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + if (Private->TextOutList[Index].TextOutEnabled) { + Status = Private->TextOutList[Index].TextOut->TestString ( + Private->TextOutList[Index].TextOut, + WString + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + // + // There is no DevNullTextOutTestString () since a Unicode buffer would + // always return EFI_SUCCESS. + // ReturnStatus will be EFI_SUCCESS if no consoles are present + // + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +/*++ + + Routine Description: + Returns information for an available text mode that the output device(s) + supports. + + Arguments: + This - Protocol instance pointer. + ModeNumber - The mode number to return information on. + Columns, Rows - Returns the geometry of the text output device for the + requested ModeNumber. + + Returns: + EFI_SUCCESS - The requested mode information was returned. + EFI_DEVICE_ERROR - The device had an error and could not + complete the request. + EFI_UNSUPPORTED - The mode number was not valid. + +--*/ +{ + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // Check whether param ModeNumber is valid. + // ModeNumber should be within range 0 ~ MaxMode - 1. + // + if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) { + return EFI_UNSUPPORTED; + } + + if ((INT32) ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + *Columns = Private->TextOutQueryData[ModeNumber].Columns; + *Rows = Private->TextOutQueryData[ModeNumber].Rows; + + if (*Columns <= 0 && *Rows <= 0) { + return EFI_UNSUPPORTED; + + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +/*++ + + Routine Description: + Sets the output device(s) to a specified mode. + + Arguments: + This - Protocol instance pointer. + ModeNumber - The mode number to set. + + Returns: + EFI_SUCCESS - The requested text mode was set. + EFI_DEVICE_ERROR - The device had an error and + could not complete the request. + EFI_UNSUPPORTED - The mode number was not valid. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + INT32 *TextOutModeMap; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // Check whether param ModeNumber is valid. + // ModeNumber should be within range 0 ~ MaxMode - 1. + // + if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) { + return EFI_UNSUPPORTED; + } + + if ((INT32) ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + // + // If the mode is being set to the curent mode, then just clear the screen and return. + // + if (Private->TextOutMode.Mode == (INT32) ModeNumber) { + return ConSplitterTextOutClearScreen (This); + } + // + // return the worst status met + // + TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber; + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + + if (Private->TextOutList[Index].TextOutEnabled) { + Status = Private->TextOutList[Index].TextOut->SetMode ( + Private->TextOutList[Index].TextOut, + TextOutModeMap[Index] + ); + // + // If this console device is based on a UGA device, then sync up the bitmap from + // the UGA splitter and reclear the text portion of the display in the new mode. + // + if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) { + Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut); + } + + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + // + // The DevNull Console will support any possible mode as it allocates memory + // + Status = DevNullTextOutSetMode (Private, ModeNumber); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ) +/*++ + + Routine Description: + Sets the background and foreground colors for the OutputString () and + ClearScreen () functions. + + Arguments: + This - Protocol instance pointer. + Attribute - The attribute to set. Bits 0..3 are the foreground color, and + bits 4..6 are the background color. All other bits are undefined + and must be zero. The valid Attributes are defined in this file. + + Returns: + EFI_SUCCESS - The attribute was set. + EFI_DEVICE_ERROR - The device had an error and + could not complete the request. + EFI_UNSUPPORTED - The attribute requested is not defined. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // Check whether param Attribute is valid. + // + if ( (Attribute > (UINTN)(((UINT32)-1)>>1)) ) { + return EFI_UNSUPPORTED; + } + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + + if (Private->TextOutList[Index].TextOutEnabled) { + Status = Private->TextOutList[Index].TextOut->SetAttribute ( + Private->TextOutList[Index].TextOut, + Attribute + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + Private->TextOutMode.Attribute = (INT32) Attribute; + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ) +/*++ + + Routine Description: + Clears the output device(s) display to the currently selected background + color. + + Arguments: + This - Protocol instance pointer. + + Returns: + EFI_SUCCESS - The operation completed successfully. + EFI_DEVICE_ERROR - The device had an error and + could not complete the request. + EFI_UNSUPPORTED - The output device is not in a valid text mode. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + + if (Private->TextOutList[Index].TextOutEnabled) { + Status = Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + Status = DevNullTextOutClearScreen (Private); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +/*++ + + Routine Description: + Sets the current coordinates of the cursor position + + Arguments: + This - Protocol instance pointer. + Column, Row - the position to set the cursor to. Must be greater than or + equal to zero and less than the number of columns and rows + by QueryMode (). + + Returns: + EFI_SUCCESS - The operation completed successfully. + EFI_DEVICE_ERROR - The device had an error and + could not complete the request. + EFI_UNSUPPORTED - The output device is not in a valid text mode, or the + cursor position is invalid for the current mode. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + UINTN MaxColumn; + UINTN MaxRow; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + MaxColumn = Private->TextOutQueryData[Private->TextOutMode.Mode].Columns; + MaxRow = Private->TextOutQueryData[Private->TextOutMode.Mode].Rows; + + if (Column >= MaxColumn || Row >= MaxRow) { + return EFI_UNSUPPORTED; + } + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + + if (Private->TextOutList[Index].TextOutEnabled) { + Status = Private->TextOutList[Index].TextOut->SetCursorPosition ( + Private->TextOutList[Index].TextOut, + Column, + Row + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + DevNullTextOutSetCursorPosition (Private, Column, Row); + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +/*++ + + Routine Description: + Makes the cursor visible or invisible + + Arguments: + This - Protocol instance pointer. + Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is + set to be invisible. + + Returns: + EFI_SUCCESS - The operation completed successfully. + EFI_DEVICE_ERROR - The device had an error and could not complete the + request, or the device does not support changing + the cursor mode. + EFI_UNSUPPORTED - The output device is not in a valid text mode. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + + if (Private->TextOutList[Index].TextOutEnabled) { + Status = Private->TextOutList[Index].TextOut->EnableCursor ( + Private->TextOutList[Index].TextOut, + Visible + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + DevNullTextOutEnableCursor (Private, Visible); + + return ReturnStatus; +} diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h new file mode 100644 index 0000000000..ac5e337689 --- /dev/null +++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h @@ -0,0 +1,667 @@ +/**@file + Private data structures for the Console Splitter driver + +Copyright (c) 2006 - 2007 Intel Corporation.
+All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _CON_SPLITTER_H_ +#define _CON_SPLITTER_H_ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +// +// Private Data Structures +// +#define CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT 32 +#define CONSOLE_SPLITTER_MODES_ALLOC_UNIT 32 +#define MAX_STD_IN_PASSWORD 80 + +typedef struct { + UINTN Columns; + UINTN Rows; +} TEXT_OUT_SPLITTER_QUERY_DATA; + +// +// Private data for the EFI_SIMPLE_TEXT_INPUT_PROTOCOL splitter +// +#define TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('T', 'i', 'S', 'p') + +typedef struct { + UINT64 Signature; + EFI_HANDLE VirtualHandle; + + EFI_SIMPLE_TEXT_INPUT_PROTOCOL TextIn; + UINTN CurrentNumberOfConsoles; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL **TextInList; + UINTN TextInListCount; + + EFI_SIMPLE_POINTER_PROTOCOL SimplePointer; + EFI_SIMPLE_POINTER_MODE SimplePointerMode; + UINTN CurrentNumberOfPointers; + EFI_SIMPLE_POINTER_PROTOCOL **PointerList; + UINTN PointerListCount; + + BOOLEAN PasswordEnabled; + CHAR16 Password[MAX_STD_IN_PASSWORD]; + UINTN PwdIndex; + CHAR16 PwdAttempt[MAX_STD_IN_PASSWORD]; + EFI_EVENT LockEvent; + + BOOLEAN KeyEventSignalState; + BOOLEAN InputEventSignalState; +} TEXT_IN_SPLITTER_PRIVATE_DATA; + +#define TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR ((a), \ + TEXT_IN_SPLITTER_PRIVATE_DATA, \ + TextIn, \ + TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +#define TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS(a) \ + CR ((a), \ + TEXT_IN_SPLITTER_PRIVATE_DATA, \ + SimplePointer, \ + TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +// +// Private data for the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL splitter +// +#define TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('T', 'o', 'S', 'p') + +typedef struct { + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; + BOOLEAN TextOutEnabled; +} TEXT_OUT_AND_GOP_DATA; + +typedef struct { + UINT32 HorizontalResolution; + UINT32 VerticalResolution; +} TEXT_OUT_GOP_MODE; + +typedef struct { + UINT64 Signature; + EFI_HANDLE VirtualHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL TextOut; + EFI_SIMPLE_TEXT_OUTPUT_MODE TextOutMode; + + EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GraphicsOutputBlt; + TEXT_OUT_GOP_MODE *GraphicsOutputModeBuffer; + UINTN CurrentNumberOfGraphicsOutput; + BOOLEAN HardwareNeedsStarting; + + EFI_CONSOLE_CONTROL_PROTOCOL ConsoleControl; + + UINTN CurrentNumberOfConsoles; + TEXT_OUT_AND_GOP_DATA *TextOutList; + UINTN TextOutListCount; + TEXT_OUT_SPLITTER_QUERY_DATA *TextOutQueryData; + UINTN TextOutQueryDataCount; + INT32 *TextOutModeMap; + + EFI_CONSOLE_CONTROL_SCREEN_MODE ConsoleOutputMode; + + UINTN DevNullColumns; + UINTN DevNullRows; + CHAR16 *DevNullScreen; + INT32 *DevNullAttributes; + +} TEXT_OUT_SPLITTER_PRIVATE_DATA; + +#define TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR ((a), \ + TEXT_OUT_SPLITTER_PRIVATE_DATA, \ + TextOut, \ + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +#define GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR ((a), \ + TEXT_OUT_SPLITTER_PRIVATE_DATA, \ + GraphicsOutput, \ + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +#define UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR ((a), \ + TEXT_OUT_SPLITTER_PRIVATE_DATA, \ + UgaDraw, \ + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +#define CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR ((a), \ + TEXT_OUT_SPLITTER_PRIVATE_DATA, \ + ConsoleControl, \ + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +// +// Function Prototypes +// +EFI_STATUS +EFIAPI +ConSplitterDriverEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +EFI_STATUS +ConSplitterTextInConstructor ( + TEXT_IN_SPLITTER_PRIVATE_DATA *Private + ) +; + +EFI_STATUS +ConSplitterTextOutConstructor ( + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +; + +// +// Driver Binding Functions +// +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +; + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +; + +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +; + +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +; + +EFI_STATUS +EFIAPI +ConSplitterComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +ConSplitterConInComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +EFI_STATUS +EFIAPI +ConSplitterConOutComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +EFI_STATUS +EFIAPI +ConSplitterStdErrComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// TextIn Constructor/Destructor functions +// +EFI_STATUS +ConSplitterTextInAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn + ) +; + +EFI_STATUS +ConSplitterTextInDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn + ) +; + +// +// SimplePointer Constuctor/Destructor functions +// +EFI_STATUS +ConSplitterSimplePointerAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer + ) +; + +EFI_STATUS +ConSplitterSimplePointerDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer + ) +; + +// +// TextOut Constuctor/Destructor functions +// +EFI_STATUS +ConSplitterTextOutAddDevice ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut, + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput, + IN EFI_UGA_DRAW_PROTOCOL *UgaDraw + ) +; + +EFI_STATUS +ConSplitterTextOutDeleteDevice ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut + ) +; + +// +// TextIn I/O Functions +// +EFI_STATUS +EFIAPI +ConSplitterTextInReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +; + +VOID +EFIAPI +ConSplitterTextInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +BOOLEAN +ConSpliterConssoleControlStdInLocked ( + VOID + ) +; + +VOID +EFIAPI +ConSpliterConsoleControlLockStdInEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +EFI_STATUS +EFIAPI +ConSpliterConsoleControlLockStdIn ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN CHAR16 *Password + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextInPrivateReadKeyStroke ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + OUT EFI_INPUT_KEY *Key + ) +; + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerReset ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerGetState ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN OUT EFI_SIMPLE_POINTER_STATE *State + ) +; + +VOID +EFIAPI +ConSplitterSimplePointerWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +// +// TextOut I/O Functions +// +VOID +ConSplitterSynchronizeModeData ( + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +; + +EFI_STATUS +ConSplitterGrowBuffer ( + IN UINTN SizeOfCount, + IN UINTN *Count, + IN OUT VOID **Buffer + ) +; + +EFI_STATUS +EFIAPI +ConSpliterConsoleControlGetMode ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, + OUT BOOLEAN *GopExists, + OUT BOOLEAN *StdInLocked + ) +; + +EFI_STATUS +EFIAPI +ConSpliterConsoleControlSetMode ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode + ) +; + +EFI_STATUS +EFIAPI +ConSpliterGraphicsOutputQueryMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +; + +EFI_STATUS +EFIAPI +ConSpliterGraphicsOutputSetMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This, + IN UINT32 ModeNumber + ) +; + +EFI_STATUS +EFIAPI +ConSpliterGraphicsOutputBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ) +; + +EFI_STATUS +DevNullGopSync ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput, + IN EFI_UGA_DRAW_PROTOCOL *UgaDraw + ) +; + + +EFI_STATUS +DevNullTextOutOutputString ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN CHAR16 *WString + ) +; + +EFI_STATUS +DevNullTextOutSetMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN UINTN ModeNumber + ) +; + +EFI_STATUS +DevNullTextOutClearScreen ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +; + +EFI_STATUS +DevNullTextOutSetCursorPosition ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN UINTN Column, + IN UINTN Row + ) +; + +EFI_STATUS +DevNullTextOutEnableCursor ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN BOOLEAN Visible + ) +; + +EFI_STATUS +DevNullSyncGopStdOut ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +; + +#endif diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.inf b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.inf new file mode 100644 index 0000000000..a5f95e4bc1 --- /dev/null +++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.inf @@ -0,0 +1,120 @@ +#/** @file +# Component description file for ConSplitter module. +# +# Any Handle that attatched EFI_CONSOLE_IDENTIFIER_PROTOCOL can be bound by this driver. +# Copyright (c) 2006 - 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ConSplitter + FILE_GUID = 408edcec-cf6d-477c-a5a8-b4844e3de281 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + ENTRY_POINT = InitializeConSplitter + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gConSplitterConInDriverBinding +# COMPONENT_NAME = gConSplitterConInComponentName +# DRIVER_BINDING = gConSplitterSimplePointerDriverBinding +# COMPONENT_NAME = gConSplitterSimplePointerComponentName +# DRIVER_BINDING = gConSplitterConOutDriverBinding +# COMPONENT_NAME = gConSplitterConOutComponentName +# DRIVER_BINDING = gConSplitterStdErrDriverBinding +# COMPONENT_NAME = gConSplitterStdErrComponentName +# + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ + +[Sources.common] + ConSplitterGraphics.c + ComponentName.c + ConSplitter.h + ConSplitter.c + CommonHeader.h + + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + + +################################################################################ +# +# Library Class Section - list of Library Classes that are required for +# this module. +# +################################################################################ + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + UefiLib + UefiDriverEntryPoint + DebugLib + + +################################################################################ +# +# Guid C Name Section - list of Guids that this module uses or produces. +# +################################################################################ + +[Guids] + gEfiConsoleInDeviceGuid # ALWAYS_CONSUMED + gEfiStandardErrorDeviceGuid # ALWAYS_CONSUMED + gEfiConsoleOutDeviceGuid # ALWAYS_CONSUMED + gEfiPrimaryConsoleOutDeviceGuid # ALWAYS_PRODUCED + gEfiPrimaryConsoleInDeviceGuid # ALWAYS_PRODUCED + gEfiPrimaryStandardErrorDeviceGuid # ALWAYS_PRODUCED + + +################################################################################ +# +# Protocol C Name Section - list of Protocol and Protocol Notify C Names +# that this module uses or produces. +# +################################################################################ + +[Protocols] + gEfiConsoleControlProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gEfiSimplePointerProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gEfiSimpleTextInProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gEfiSimpleTextOutProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gEfiGraphicsOutputProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gEfiUgaDrawProtocolGuid # PROTOCOL ALWAYS_PRODUCED + diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.msa b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.msa new file mode 100644 index 0000000000..afc35028ea --- /dev/null +++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.msa @@ -0,0 +1,126 @@ + + + + ConSplitter + DXE_DRIVER + 408edcec-cf6d-477c-a5a8-b4844e3de281 + 1.0 + Component description file for ConSplitter module. + Any Handle that attatched EFI_CONSOLE_IDENTIFIER_PROTOCOL can be bound by this driver. + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + ConSplitter + + + + DebugLib + Recommended libary Instance is PeiDxeDebugLibReportStatusCode instance in MdePkg. + + + UefiDriverModelLib + + + UefiDriverEntryPoint + + + UefiLib + + + BaseLib + + + BaseMemoryLib + + + MemoryAllocationLib + + + UefiBootServicesTableLib + + + + ConSplitter.c + ConSplitter.h + ComponentName.c + ConSplitterGraphics.c + + + + + + + + gEfiUgaDrawProtocolGuid + UGA Draw protocol is only installed in EFI mode. + + + gEfiGraphicsOutputProtocolGuid + Graphics Output Protocol is only installed in UEFI mode. + + + gEfiSimpleTextOutProtocolGuid + + + gEfiSimpleTextInProtocolGuid + + + gEfiSimplePointerProtocolGuid + + + gEfiConsoleControlProtocolGuid + + + + + gEfiPrimaryStandardErrorDeviceGuid + + + gEfiPrimaryConsoleInDeviceGuid + + + gEfiPrimaryConsoleOutDeviceGuid + + + gEfiConsoleOutDeviceGuid + + + gEfiStandardErrorDeviceGuid + + + gEfiConsoleInDeviceGuid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + ConSplitterDriverEntry + + + gConSplitterConInDriverBinding + gConSplitterConInComponentName + + + gConSplitterSimplePointerDriverBinding + gConSplitterSimplePointerComponentName + + + gConSplitterConOutDriverBinding + gConSplitterConOutComponentName + + + gConSplitterStdErrDriverBinding + gConSplitterStdErrComponentName + + + \ No newline at end of file diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c new file mode 100644 index 0000000000..0387324fcf --- /dev/null +++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c @@ -0,0 +1,1222 @@ +/*++ + +Copyright (c) 2006 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ConSplitterGraphics.c + +Abstract: + + Support for ConsoleControl protocol. Support for UGA Draw spliter. + Support for DevNull Console Out. This console uses memory buffers + to represnt the console. It allows a console to start very early and + when a new console is added it is synced up with the current console + +--*/ + + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "ConSplitter.h" + +#include + +static CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL }; + +EFI_STATUS +EFIAPI +ConSpliterConsoleControlGetMode ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, + OUT BOOLEAN *GopExists, + OUT BOOLEAN *StdInLocked + ) +/*++ + + Routine Description: + Return the current video mode information. Also returns info about existence + of UGA Draw devices in system, and if the Std In device is locked. All the + arguments are optional and only returned if a non NULL pointer is passed in. + + Arguments: + This - Protocol instance pointer. + Mode - Are we in text of grahics mode. + UgaExists - TRUE if UGA Spliter has found a UGA device + StdInLocked - TRUE if StdIn device is keyboard locked + + Returns: + EFI_SUCCESS - Mode information returned. + EFI_INVALID_PARAMETER - Invalid parameters. + +--*/ +{ + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + if (Mode == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Mode = Private->ConsoleOutputMode; + + if (GopExists != NULL) { + *GopExists = FALSE; + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) { + *GopExists = TRUE; + break; + } + } + } + + if (StdInLocked != NULL) { + *StdInLocked = ConSpliterConssoleControlStdInLocked (); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConSpliterConsoleControlSetMode ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode + ) +/*++ + + Routine Description: + Set the current mode to either text or graphics. Graphics is + for Quiet Boot. + + Arguments: + This - Protocol instance pointer. + Mode - Mode to set the + + Returns: + EFI_SUCCESS - Mode information returned. + EFI_INVALID_PARAMETER - Invalid parameter. + EFI_UNSUPPORTED - Operation unsupported. + +--*/ +{ + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + TEXT_OUT_AND_GOP_DATA *TextAndGop; + BOOLEAN Supported; + + Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + if (Mode >= EfiConsoleControlScreenMaxValue) { + return EFI_INVALID_PARAMETER; + } + + // + // Judge current mode with wanted mode at first. + // + if (Private->ConsoleOutputMode == Mode) { + return EFI_SUCCESS; + } + + Supported = FALSE; + TextAndGop = &Private->TextOutList[0]; + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndGop++) { + if ((TextAndGop->GraphicsOutput != NULL) || (TextAndGop->UgaDraw != NULL)) { + Supported = TRUE; + break; + } + } + + if ((!Supported) && (Mode == EfiConsoleControlScreenGraphics)) { + return EFI_UNSUPPORTED; + } + + Private->ConsoleOutputMode = Mode; + + TextAndGop = &Private->TextOutList[0]; + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndGop++) { + + TextAndGop->TextOutEnabled = TRUE; + // + // If we are going into Graphics mode disable ConOut to any UGA device + // + if ((Mode == EfiConsoleControlScreenGraphics) &&((TextAndGop->GraphicsOutput != NULL) || (TextAndGop->UgaDraw != NULL))) { + TextAndGop->TextOutEnabled = FALSE; + DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw); + } + } + + if (Mode == EfiConsoleControlScreenText) { + DevNullSyncGopStdOut (Private); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConSpliterGraphicsOutputQueryMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +/*++ + + Routine Description: + Return the current video mode information. + + Arguments: + This - Protocol instance pointer. + ModeNumber - The mode number to return information on. + Info - Caller allocated buffer that returns information about ModeNumber. + SizeOfInfo - A pointer to the size, in bytes, of the Info buffer. + + Returns: + EFI_SUCCESS - Mode information returned. + EFI_BUFFER_TOO_SMALL - The Info buffer was too small. + EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode. + EFI_NOT_STARTED - Video display is not initialized. Call SetMode () + EFI_INVALID_PARAMETER - One of the input args was NULL. + +--*/ +{ + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + TEXT_OUT_GOP_MODE *Mode; + + if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) { + return EFI_INVALID_PARAMETER; + } + + // + // retrieve private data + // + Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + if (Private->HardwareNeedsStarting) { + return EFI_NOT_STARTED; + } + + *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)); + + if (*Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + + CopyMem (*Info, Private->GraphicsOutput.Mode->Info, *SizeOfInfo); + Mode = &Private->GraphicsOutputModeBuffer[ModeNumber]; + (*Info)->HorizontalResolution = Mode->HorizontalResolution; + (*Info)->VerticalResolution = Mode->VerticalResolution; + (*Info)->PixelsPerScanLine = Mode->HorizontalResolution; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConSpliterGraphicsOutputSetMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This, + IN UINT32 ModeNumber + ) +/*++ + +Routine Description: + + Graphics output protocol interface to set video mode + + Arguments: + This - Protocol instance pointer. + ModeNumber - The mode number to be set. + + Returns: + EFI_SUCCESS - Graphics mode was changed. + EFI_DEVICE_ERROR - The device had an error and could not complete the request. + EFI_UNSUPPORTED - ModeNumber is not supported by this device. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + TEXT_OUT_GOP_MODE *Mode; + UINTN Size; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + UINTN NumberIndex; + UINTN SizeOfInfo; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + + if (ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + if (ModeNumber == This->Mode->Mode) { + return EFI_SUCCESS; + } + + Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // GopDevNullSetMode () + // + ReturnStatus = EFI_SUCCESS; + + // + // Free the old version + // + if (Private->GraphicsOutputBlt != NULL) { + FreePool (Private->GraphicsOutputBlt); + } + + // + // Allocate the virtual Blt buffer + // + Mode = &Private->GraphicsOutputModeBuffer[ModeNumber]; + Size = Mode->HorizontalResolution * Mode->VerticalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + Private->GraphicsOutputBlt = AllocateZeroPool (Size); + + if (Private->GraphicsOutputBlt == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (!Private->HardwareNeedsStarting) { + if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) { + return EFI_UNSUPPORTED; + } + } + // + // return the worst status met + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + GraphicsOutput = Private->TextOutList[Index].GraphicsOutput; + if (GraphicsOutput != NULL) { + // + // Find corresponding ModeNumber of this GraphicsOutput instance + // + for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) { + Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info); + if (EFI_ERROR (Status)) { + return Status; + } + if ((Info->HorizontalResolution == Mode->HorizontalResolution) && (Info->VerticalResolution == Mode->VerticalResolution)) { + FreePool (Info); + break; + } + FreePool (Info); + } + + Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + UgaDraw = Private->TextOutList[Index].UgaDraw; + if (UgaDraw != NULL) { + Status = UgaDraw->SetMode ( + UgaDraw, + Mode->HorizontalResolution, + Mode->VerticalResolution, + 32, + 60 + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + This->Mode->Mode = ModeNumber; + + Info = This->Mode->Info; + Info->HorizontalResolution = Mode->HorizontalResolution; + Info->VerticalResolution = Mode->VerticalResolution; + Info->PixelsPerScanLine = Mode->HorizontalResolution; + + // + // Information is not enough here, so the following items remain unchanged: + // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat + // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize + // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter. + // + + Private->HardwareNeedsStarting = FALSE; + + return ReturnStatus; +} + +STATIC +EFI_STATUS +DevNullGraphicsOutputBlt ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ) +{ + UINTN SrcY; + BOOLEAN Forward; + UINTN Index; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPtr; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ScreenPtr; + UINTN HorizontalResolution; + UINTN VerticalResolution; + + if ((BltOperation < EfiBltVideoFill) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) { + return EFI_INVALID_PARAMETER; + } + + if (Width == 0 || Height == 0) { + return EFI_INVALID_PARAMETER; + } + + if (Delta == 0) { + Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + } + + HorizontalResolution = Private->GraphicsOutput.Mode->Info->HorizontalResolution; + VerticalResolution = Private->GraphicsOutput.Mode->Info->VerticalResolution; + + // + // We need to fill the Virtual Screen buffer with the blt data. + // + if (BltOperation == EfiBltVideoToBltBuffer) { + // + // Video to BltBuffer: Source is Video, destination is BltBuffer + // + if ((SourceY + Height) > VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if ((SourceX + Width) > HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + + BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + ScreenPtr = &Private->GraphicsOutputBlt[SourceY * HorizontalResolution + SourceX]; + while (Height) { + CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltPtr + Delta); + ScreenPtr += HorizontalResolution; + Height--; + } + } else { + // + // BltBuffer to Video: Source is BltBuffer, destination is Video + // + if (DestinationY + Height > VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (DestinationX + Width > HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + + if ((BltOperation == EfiBltVideoToVideo) && (DestinationY > SourceY)) { + // + // Copy backwards, only care the Video to Video Blt + // + ScreenPtr = &Private->GraphicsOutputBlt[(DestinationY + Height - 1) * HorizontalResolution + DestinationX]; + SrcY = SourceY + Height - 1; + Forward = FALSE; + } else { + // + // Copy forwards, for other cases + // + ScreenPtr = &Private->GraphicsOutputBlt[DestinationY * HorizontalResolution + DestinationX]; + SrcY = SourceY; + Forward = TRUE; + } + + while (Height != 0) { + if (BltOperation == EfiBltVideoFill) { + for (Index = 0; Index < Width; Index++) { + ScreenPtr[Index] = *BltBuffer; + } + } else { + if (BltOperation == EfiBltBufferToVideo) { + BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + } else { + BltPtr = &Private->GraphicsOutputBlt[SrcY * HorizontalResolution + SourceX]; + } + + CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + } + + if (Forward) { + ScreenPtr += HorizontalResolution; + SrcY ++; + } else { + ScreenPtr -= HorizontalResolution; + SrcY --; + } + Height--; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConSpliterGraphicsOutputBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ) +/*++ + + Routine Description: + The following table defines actions for BltOperations: + EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY) + directly to every pixel of the video display rectangle + (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). + Only one pixel will be used from the BltBuffer. Delta is NOT used. + EfiBltVideoToBltBuffer - Read data from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + the BltBuffer rectangle (DestinationX, DestinationY ) + (DestinationX + Width, DestinationY + Height). If DestinationX or + DestinationY is not zero then Delta must be set to the length in bytes + of a row in the BltBuffer. + EfiBltBufferToVideo - Write data from the BltBuffer rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + not zero then Delta must be set to the length in bytes of a row in the + BltBuffer. + EfiBltVideoToVideo - Copy from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) . + to the video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). + The BltBuffer and Delta are not used in this mode. + + Arguments: + This - Protocol instance pointer. + BltBuffer - Buffer containing data to blit into video buffer. This + buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + BltOperation - Operation to perform on BlitBuffer and video memory + SourceX - X coordinate of source for the BltBuffer. + SourceY - Y coordinate of source for the BltBuffer. + DestinationX - X coordinate of destination for the BltBuffer. + DestinationY - Y coordinate of destination for the BltBuffer. + Width - Width of rectangle in BltBuffer in pixels. + Height - Hight of rectangle in BltBuffer in pixels. + Delta - + + Returns: + EFI_SUCCESS - The Blt operation completed. + EFI_INVALID_PARAMETER - BltOperation is not valid. + EFI_DEVICE_ERROR - A hardware error occured writting to the video + buffer. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + + Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // Sync up DevNull GOP device + // + ReturnStatus = DevNullGraphicsOutputBlt ( + Private, + BltBuffer, + BltOperation, + SourceX, + SourceY, + DestinationX, + DestinationY, + Width, + Height, + Delta + ); + + if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) { + return ReturnStatus; + } + // + // return the worst status met + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + GraphicsOutput = Private->TextOutList[Index].GraphicsOutput; + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->Blt ( + GraphicsOutput, + BltBuffer, + BltOperation, + SourceX, + SourceY, + DestinationX, + DestinationY, + Width, + Height, + Delta + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } else if (BltOperation == EfiBltVideoToBltBuffer) { + // + // Only need to read the data into buffer one time + // + return EFI_SUCCESS; + } + } + + UgaDraw = Private->TextOutList[Index].UgaDraw; + if (UgaDraw != NULL) { + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) BltBuffer, + (EFI_UGA_BLT_OPERATION) BltOperation, + SourceX, + SourceY, + DestinationX, + DestinationY, + Width, + Height, + Delta + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } else if (BltOperation == EfiBltVideoToBltBuffer) { + // + // Only need to read the data into buffer one time + // + return EFI_SUCCESS; + } + } + } + + return ReturnStatus; +} + +EFI_STATUS +DevNullGopSync ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput, + IN EFI_UGA_DRAW_PROTOCOL *UgaDraw + ) +{ + if (GraphicsOutput != NULL) { + return GraphicsOutput->Blt ( + GraphicsOutput, + Private->GraphicsOutputBlt, + EfiBltBufferToVideo, + 0, + 0, + 0, + 0, + Private->GraphicsOutput.Mode->Info->HorizontalResolution, + Private->GraphicsOutput.Mode->Info->VerticalResolution, + 0 + ); + } else { + return UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) Private->GraphicsOutputBlt, + EfiUgaBltBufferToVideo, + 0, + 0, + 0, + 0, + Private->GraphicsOutput.Mode->Info->HorizontalResolution, + Private->GraphicsOutput.Mode->Info->VerticalResolution, + 0 + ); + } +} + + +EFI_STATUS +DevNullTextOutOutputString ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN CHAR16 *WString + ) +/*++ + + Routine Description: + Write a Unicode string to the output device. + + Arguments: + Private - Pointer to the console output splitter's private data. It + indicates the calling context. + WString - The NULL-terminated Unicode string to be displayed on the output + device(s). All output devices must also support the Unicode + drawing defined in this file. + + Returns: + EFI_SUCCESS - The string was output to the device. + EFI_DEVICE_ERROR - The device reported an error while attempting to + output the text. + EFI_UNSUPPORTED - The output device's mode is not currently in a + defined text mode. + EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the + characters in the Unicode string could not be + rendered and were skipped. + +--*/ +{ + UINTN SizeScreen; + UINTN SizeAttribute; + UINTN Index; + EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; + CHAR16 *Screen; + CHAR16 *NullScreen; + CHAR16 InsertChar; + CHAR16 TempChar; + CHAR16 *PStr; + INT32 *Attribute; + INT32 *NullAttributes; + INT32 CurrentWidth; + UINTN LastRow; + UINTN MaxColumn; + + Mode = &Private->TextOutMode; + NullScreen = Private->DevNullScreen; + NullAttributes = Private->DevNullAttributes; + LastRow = Private->DevNullRows - 1; + MaxColumn = Private->DevNullColumns; + + if (Mode->Attribute & EFI_WIDE_ATTRIBUTE) { + CurrentWidth = 2; + } else { + CurrentWidth = 1; + } + + while (*WString) { + + if (*WString == CHAR_BACKSPACE) { + // + // If the cursor is at the left edge of the display, then move the cursor + // one row up. + // + if (Mode->CursorColumn == 0 && Mode->CursorRow > 0) { + Mode->CursorRow--; + Mode->CursorColumn = (INT32) MaxColumn; + } + + // + // If the cursor is not at the left edge of the display, + // then move the cursor left one column. + // + if (Mode->CursorColumn > 0) { + Mode->CursorColumn--; + if (Mode->CursorColumn > 0 && + NullAttributes[Mode->CursorRow * MaxColumn + Mode->CursorColumn - 1] & EFI_WIDE_ATTRIBUTE + ) { + Mode->CursorColumn--; + + // + // Insert an extra backspace + // + InsertChar = CHAR_BACKSPACE; + PStr = WString + 1; + while (*PStr) { + TempChar = *PStr; + *PStr = InsertChar; + InsertChar = TempChar; + PStr++; + } + + *PStr = InsertChar; + *(++PStr) = 0; + + WString++; + } + } + + WString++; + + } else if (*WString == CHAR_LINEFEED) { + // + // If the cursor is at the bottom of the display, + // then scroll the display one row, and do not update + // the cursor position. Otherwise, move the cursor down one row. + // + if (Mode->CursorRow == (INT32) (LastRow)) { + // + // Scroll Screen Up One Row + // + SizeAttribute = LastRow * MaxColumn; + CopyMem ( + NullAttributes, + NullAttributes + MaxColumn, + SizeAttribute * sizeof (INT32) + ); + + // + // Each row has an ending CHAR_NULL. So one more character each line + // for DevNullScreen than DevNullAttributes + // + SizeScreen = SizeAttribute + LastRow; + CopyMem ( + NullScreen, + NullScreen + (MaxColumn + 1), + SizeScreen * sizeof (CHAR16) + ); + + // + // Print Blank Line at last line + // + Screen = NullScreen + SizeScreen; + Attribute = NullAttributes + SizeAttribute; + + for (Index = 0; Index < MaxColumn; Index++, Screen++, Attribute++) { + *Screen = ' '; + *Attribute = Mode->Attribute; + } + } else { + Mode->CursorRow++; + } + + WString++; + } else if (*WString == CHAR_CARRIAGE_RETURN) { + // + // Move the cursor to the beginning of the current row. + // + Mode->CursorColumn = 0; + WString++; + } else { + // + // Print the character at the current cursor position and + // move the cursor right one column. If this moves the cursor + // past the right edge of the display, then the line should wrap to + // the beginning of the next line. This is equivalent to inserting + // a CR and an LF. Note that if the cursor is at the bottom of the + // display, and the line wraps, then the display will be scrolled + // one line. + // + Index = Mode->CursorRow * MaxColumn + Mode->CursorColumn; + + while (Mode->CursorColumn < (INT32) MaxColumn) { + if (*WString == CHAR_NULL) { + break; + } + + if (*WString == CHAR_BACKSPACE) { + break; + } + + if (*WString == CHAR_LINEFEED) { + break; + } + + if (*WString == CHAR_CARRIAGE_RETURN) { + break; + } + + if (*WString == WIDE_CHAR || *WString == NARROW_CHAR) { + CurrentWidth = (*WString == WIDE_CHAR) ? 2 : 1; + WString++; + continue; + } + + if (Mode->CursorColumn + CurrentWidth > (INT32) MaxColumn) { + // + // If a wide char is at the rightmost column, then move the char + // to the beginning of the next row + // + NullScreen[Index + Mode->CursorRow] = L' '; + NullAttributes[Index] = Mode->Attribute | (UINT32) EFI_WIDE_ATTRIBUTE; + Index++; + Mode->CursorColumn++; + } else { + NullScreen[Index + Mode->CursorRow] = *WString; + NullAttributes[Index] = Mode->Attribute; + if (CurrentWidth == 1) { + NullAttributes[Index] &= (~ (UINT32) EFI_WIDE_ATTRIBUTE); + } else { + NullAttributes[Index] |= (UINT32) EFI_WIDE_ATTRIBUTE; + NullAttributes[Index + 1] &= (~ (UINT32) EFI_WIDE_ATTRIBUTE); + } + + Index += CurrentWidth; + WString++; + Mode->CursorColumn += CurrentWidth; + } + } + // + // At the end of line, output carriage return and line feed + // + if (Mode->CursorColumn >= (INT32) MaxColumn) { + DevNullTextOutOutputString (Private, mCrLfString); + } + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +DevNullTextOutSetMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN UINTN ModeNumber + ) +/*++ + + Routine Description: + Sets the output device(s) to a specified mode. + + Arguments: + Private - Private data structure pointer. + ModeNumber - The mode number to set. + + Returns: + EFI_SUCCESS - The requested text mode was set. + EFI_DEVICE_ERROR - The device had an error and + could not complete the request. + EFI_UNSUPPORTED - The mode number was not valid. + EFI_OUT_OF_RESOURCES - Out of resources. + +--*/ +{ + UINTN Size; + UINTN Row; + UINTN Column; + TEXT_OUT_SPLITTER_QUERY_DATA *Mode; + + // + // No extra check for ModeNumber here, as it has been checked in + // ConSplitterTextOutSetMode. And mode 0 should always be supported. + // + Mode = &(Private->TextOutQueryData[ModeNumber]); + Row = Mode->Rows; + Column = Mode->Columns; + + if (Row <= 0 && Column <= 0) { + return EFI_UNSUPPORTED; + } + + if (Private->DevNullColumns != Column || Private->DevNullRows != Row) { + + Private->TextOutMode.Mode = (INT32) ModeNumber; + Private->DevNullColumns = Column; + Private->DevNullRows = Row; + + if (Private->DevNullScreen != NULL) { + FreePool (Private->DevNullScreen); + } + + Size = (Row * (Column + 1)) * sizeof (CHAR16); + Private->DevNullScreen = AllocateZeroPool (Size); + if (Private->DevNullScreen == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (Private->DevNullAttributes != NULL) { + FreePool (Private->DevNullAttributes); + } + + Size = Row * Column * sizeof (INT32); + Private->DevNullAttributes = AllocateZeroPool (Size); + if (Private->DevNullAttributes == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + + DevNullTextOutClearScreen (Private); + + return EFI_SUCCESS; +} + +EFI_STATUS +DevNullTextOutClearScreen ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +/*++ + + Routine Description: + Clears the output device(s) display to the currently selected background + color. + + Arguments: + Private - Protocol instance pointer. + + Returns: + EFI_SUCCESS - The operation completed successfully. + EFI_DEVICE_ERROR - The device had an error and + could not complete the request. + EFI_UNSUPPORTED - The output device is not in a valid text mode. + +--*/ +{ + UINTN Row; + UINTN Column; + CHAR16 *Screen; + INT32 *Attributes; + INT32 CurrentAttribute; + + // + // Clear the DevNull Text Out Buffers. + // The screen is filled with spaces. + // The attributes are all synced with the current Simple Text Out Attribute + // + Screen = Private->DevNullScreen; + Attributes = Private->DevNullAttributes; + CurrentAttribute = Private->TextOutMode.Attribute; + + for (Row = 0; Row < Private->DevNullRows; Row++) { + for (Column = 0; Column < Private->DevNullColumns; Column++, Screen++, Attributes++) { + *Screen = ' '; + *Attributes = CurrentAttribute; + } + // + // Each line of the screen has a NULL on the end so we must skip over it + // + Screen++; + } + + DevNullTextOutSetCursorPosition (Private, 0, 0); + + return DevNullTextOutEnableCursor (Private, TRUE); +} + +EFI_STATUS +DevNullTextOutSetCursorPosition ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN UINTN Column, + IN UINTN Row + ) +/*++ + + Routine Description: + Sets the current coordinates of the cursor position + + Arguments: + Private - Protocol instance pointer. + Column, Row - the position to set the cursor to. Must be greater than or + equal to zero and less than the number of columns and rows + by QueryMode (). + + Returns: + EFI_SUCCESS - The operation completed successfully. + EFI_DEVICE_ERROR - The device had an error and + could not complete the request. + EFI_UNSUPPORTED - The output device is not in a valid text mode, or the + cursor position is invalid for the current mode. + +--*/ +{ + // + // No need to do extra check here as whether (Column, Row) is valid has + // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should + // always be supported. + // + Private->TextOutMode.CursorColumn = (INT32) Column; + Private->TextOutMode.CursorRow = (INT32) Row; + + return EFI_SUCCESS; +} + +EFI_STATUS +DevNullTextOutEnableCursor ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN BOOLEAN Visible + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.EnableCursor(). + In this driver, the cursor cannot be hidden. + + Arguments: + + Private - Indicates the calling context. + + Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor + is set to be invisible. + + Returns: + + EFI_SUCCESS - The request is valid. + + +--*/ +{ + Private->TextOutMode.CursorVisible = Visible; + + return EFI_SUCCESS; +} + +EFI_STATUS +DevNullSyncGopStdOut ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +/*++ + Routine Description: + Take the DevNull TextOut device and update the Simple Text Out on every + UGA device. + + Arguments: + Private - Indicates the calling context. + + Returns: + EFI_SUCCESS - The request is valid. + other - Return status of TextOut->OutputString () + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + UINTN Row; + UINTN Column; + UINTN List; + UINTN MaxColumn; + UINTN CurrentColumn; + UINTN StartRow; + UINTN StartColumn; + INT32 StartAttribute; + BOOLEAN StartCursorState; + CHAR16 *Screen; + CHAR16 *Str; + CHAR16 *Buffer; + CHAR16 *BufferTail; + CHAR16 *ScreenStart; + INT32 CurrentAttribute; + INT32 *Attributes; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto; + + // + // Save the devices Attributes, Cursor enable state and location + // + StartColumn = Private->TextOutMode.CursorColumn; + StartRow = Private->TextOutMode.CursorRow; + StartAttribute = Private->TextOutMode.Attribute; + StartCursorState = Private->TextOutMode.CursorVisible; + + for (List = 0; List < Private->CurrentNumberOfConsoles; List++) { + + Sto = Private->TextOutList[List].TextOut; + + // + // Skip non GOP/UGA devices + // + if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) { + Sto->EnableCursor (Sto, FALSE); + Sto->ClearScreen (Sto); + } + } + + ReturnStatus = EFI_SUCCESS; + Screen = Private->DevNullScreen; + Attributes = Private->DevNullAttributes; + MaxColumn = Private->DevNullColumns; + + Buffer = AllocateZeroPool ((MaxColumn + 1) * sizeof (CHAR16)); + + for (Row = 0; Row < Private->DevNullRows; Row++, Screen += (MaxColumn + 1), Attributes += MaxColumn) { + + if (Row == (Private->DevNullRows - 1)) { + // + // Don't ever sync the last character as it will scroll the screen + // + Screen[MaxColumn - 1] = 0x00; + } + + Column = 0; + while (Column < MaxColumn) { + if (Screen[Column]) { + CurrentAttribute = Attributes[Column]; + CurrentColumn = Column; + ScreenStart = &Screen[Column]; + + // + // the line end is alway 0x0. So Column should be less than MaxColumn + // It should be still in the same row + // + for (Str = ScreenStart, BufferTail = Buffer; *Str != 0; Str++, Column++) { + + if (Attributes[Column] != CurrentAttribute) { + Column--; + break; + } + + *BufferTail = *Str; + BufferTail++; + if (Attributes[Column] & EFI_WIDE_ATTRIBUTE) { + Str++; + Column++; + } + } + + *BufferTail = 0; + + for (List = 0; List < Private->CurrentNumberOfConsoles; List++) { + + Sto = Private->TextOutList[List].TextOut; + + // + // Skip non GOP/UGA devices + // + if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) { + Sto->SetAttribute (Sto, CurrentAttribute); + Sto->SetCursorPosition (Sto, CurrentColumn, Row); + Status = Sto->OutputString (Sto, Buffer); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + } + + Column++; + } + } + // + // Restore the devices Attributes, Cursor enable state and location + // + for (List = 0; List < Private->CurrentNumberOfConsoles; List++) { + Sto = Private->TextOutList[List].TextOut; + + // + // Skip non GOP/UGA devices + // + if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) { + Sto->SetAttribute (Sto, StartAttribute); + Sto->SetCursorPosition (Sto, StartColumn, StartRow); + Status = Sto->EnableCursor (Sto, StartCursorState); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + FreePool (Buffer); + + return ReturnStatus; +} diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/CommonHeader.h b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/CommonHeader.h new file mode 100644 index 0000000000..ad94d88d86 --- /dev/null +++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/CommonHeader.h @@ -0,0 +1,47 @@ +/**@file + Common header file shared by all source files. + + This file includes package header files, library classes and protocol, PPI & GUID definitions. + + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + + +// +// The package level header files this module uses +// +#include +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +// +// Driver Binding Externs +// +extern EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gGraphicsConsoleComponentName; + +#endif diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/ComponentName.c b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/ComponentName.c new file mode 100644 index 0000000000..b739e13564 --- /dev/null +++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/ComponentName.c @@ -0,0 +1,144 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "GraphicsConsole.h" + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gGraphicsConsoleComponentName = { + GraphicsConsoleComponentNameGetDriverName, + GraphicsConsoleComponentNameGetControllerName, + "eng" +}; + +STATIC EFI_UNICODE_STRING_TABLE mGraphicsConsoleDriverNameTable[] = { + { + "eng", + (CHAR16 *)L"UGA Console Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +GraphicsConsoleComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gGraphicsConsoleComponentName.SupportedLanguages, + mGraphicsConsoleDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +GraphicsConsoleComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/ComponentName.h b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/ComponentName.h new file mode 100644 index 0000000000..1067b96677 --- /dev/null +++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/ComponentName.h @@ -0,0 +1,56 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ComponentName.h + +Abstract: + + +Revision History + +--*/ + +#ifndef _GRAPHICS_CONSOLE_COMPONENT_NAME_H +#define _GRAPHICS_CONSOLE_COMPONENT_NAME_H + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +extern EFI_COMPONENT_NAME_PROTOCOL gGraphicsConsoleComponentName; + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +GraphicsConsoleComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +; + +EFI_STATUS +EFIAPI +GraphicsConsoleComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +; + +#endif diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/EntryPoint.c b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/EntryPoint.c new file mode 100644 index 0000000000..627ad4109d --- /dev/null +++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/EntryPoint.c @@ -0,0 +1,56 @@ +/**@file + Entry Point Source file. + + This file contains the user entry point + + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +/** + The user Entry Point for module GraphicsConsole. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeGraphicsConsole( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gGraphicsConsoleDriverBinding, + ImageHandle, + &gGraphicsConsoleComponentName, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + + return Status; +} diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c new file mode 100644 index 0000000000..aecbb206a9 --- /dev/null +++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c @@ -0,0 +1,1826 @@ +/**@file + This is the main routine for initializing the Graphics Console support routines. +Remaining Tasks + Add all standard Glyphs from EFI 1.02 Specification + Implement optimal automatic Mode creation algorithm + Solve palette issues for mixed graphics and text + When does this protocol reset the palette? + +Copyright (c) 2006 - 2007 Intel Corporation.
+All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "GraphicsConsole.h" + +STATIC +EFI_STATUS +GetTextColors ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground, + OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background + ); + +STATIC +EFI_STATUS +DrawUnicodeWeightAtCursorN ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *UnicodeWeight, + IN UINTN Count + ); + +STATIC +EFI_STATUS +EraseCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ); + +// +// Globals +// +GRAPHICS_CONSOLE_DEV mGraphicsConsoleDevTemplate = { + GRAPHICS_CONSOLE_DEV_SIGNATURE, + (EFI_GRAPHICS_OUTPUT_PROTOCOL *) NULL, + (EFI_UGA_DRAW_PROTOCOL *) NULL, + { + GraphicsConsoleConOutReset, + GraphicsConsoleConOutOutputString, + GraphicsConsoleConOutTestString, + GraphicsConsoleConOutQueryMode, + GraphicsConsoleConOutSetMode, + GraphicsConsoleConOutSetAttribute, + GraphicsConsoleConOutClearScreen, + GraphicsConsoleConOutSetCursorPosition, + GraphicsConsoleConOutEnableCursor, + (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL + }, + { + 0, + 0, + EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK), + 0, + 0, + TRUE + }, + { + { 80, 25, 0, 0, 0, 0 }, // Mode 0 + { 80, 50, 0, 0, 0, 0 }, // Mode 1 + { 0, 0, 0, 0, 0, 0 } // Mode 2 + }, + (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL, + (EFI_HII_HANDLE) 0 +}; + +EFI_HII_PROTOCOL *mHii; + +static CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL }; + +static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors[16] = { + // + // B G R + // + {0x00, 0x00, 0x00, 0x00}, // BLACK + {0x98, 0x00, 0x00, 0x00}, // BLUE + {0x00, 0x98, 0x00, 0x00}, // GREEN + {0x98, 0x98, 0x00, 0x00}, // CYAN + {0x00, 0x00, 0x98, 0x00}, // RED + {0x98, 0x00, 0x98, 0x00}, // MAGENTA + {0x00, 0x98, 0x98, 0x00}, // BROWN + {0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY + {0x30, 0x30, 0x30, 0x00}, // DARKGRAY - BRIGHT BLACK + {0xff, 0x00, 0x00, 0x00}, // LIGHTBLUE - ? + {0x00, 0xff, 0x00, 0x00}, // LIGHTGREEN - ? + {0xff, 0xff, 0x00, 0x00}, // LIGHTCYAN + {0x00, 0x00, 0xff, 0x00}, // LIGHTRED + {0xff, 0x00, 0xff, 0x00}, // LIGHTMAGENTA + {0x00, 0xff, 0xff, 0x00}, // LIGHTBROWN + {0xff, 0xff, 0xff, 0x00} // WHITE +}; + +static EFI_NARROW_GLYPH mCursorGlyph = { + 0x0000, + 0x00, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF } +}; + +EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding = { + GraphicsConsoleControllerDriverSupported, + GraphicsConsoleControllerDriverStart, + GraphicsConsoleControllerDriverStop, + 0xa, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + UgaDraw = NULL; + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &GraphicsOutput, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + GraphicsOutput = NULL; + // + // Open Graphics Output Protocol failed, try to open UGA Draw Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiUgaDrawProtocolGuid, + (VOID **) &UgaDraw, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // We need to ensure that we do not layer on top of a virtual handle. + // We need to ensure that the handles produced by the conspliter do not + // get used. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else { + goto Error; + } + // + // Does Hii Exist? If not, we aren't ready to run + // + Status = EfiLocateHiiProtocol (); + + // + // Close the I/O Abstraction(s) used to perform the supported test + // +Error: + if (GraphicsOutput != NULL) { + gBS->CloseProtocol ( + Controller, + &gEfiGraphicsOutputProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else { + gBS->CloseProtocol ( + Controller, + &gEfiUgaDrawProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + return Status; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Start the controller. + + Arguments: + + This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + Controller - The handle of the controller to start. + RemainingDevicePath - A pointer to the remaining portion of a devcie path. + + Returns: + + EFI_SUCCESS - Return successfully. + EFI_OUT_OF_RESOURCES - Out of resources. + +--*/ +{ + EFI_STATUS Status; + GRAPHICS_CONSOLE_DEV *Private; + EFI_HII_PACKAGES *Package; + EFI_HII_FONT_PACK *FontPack; + UINTN NarrowFontSize; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 ColorDepth; + UINT32 RefreshRate; + UINTN MaxMode; + UINTN Columns; + UINTN Rows; + UINT8 *Location; + UINT32 ModeNumber; + UINTN SizeOfInfo; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + + ModeNumber = 0; + + // + // Initialize the Graphics Console device instance + // + Private = AllocateCopyPool ( + sizeof (GRAPHICS_CONSOLE_DEV), + &mGraphicsConsoleDevTemplate + ); + if (Private == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Private->SimpleTextOutput.Mode = &(Private->SimpleTextOutputMode); + + Status = gBS->OpenProtocol ( + Controller, + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &Private->GraphicsOutput, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR(Status)) { + Private->GraphicsOutput = NULL; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiUgaDrawProtocolGuid, + (VOID **) &Private->UgaDraw, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Error; + } + } + + // + // Get the HII protocol. If Supported() succeeds, do we really + // need to get HII protocol again? + // + Status = EfiLocateHiiProtocol (); + if (EFI_ERROR (Status)) { + goto Error; + } + + NarrowFontSize = ReturnNarrowFontSize (); + + FontPack = AllocateZeroPool (sizeof (EFI_HII_FONT_PACK) + NarrowFontSize); + ASSERT (FontPack); + + FontPack->Header.Length = (UINT32) (sizeof (EFI_HII_FONT_PACK) + NarrowFontSize); + FontPack->Header.Type = EFI_HII_FONT; + FontPack->NumberOfNarrowGlyphs = (UINT16) (NarrowFontSize / sizeof (EFI_NARROW_GLYPH)); + + Location = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)); + CopyMem (Location, UsStdNarrowGlyphData, NarrowFontSize); + + // + // Register our Fonts into the global database + // + Package = PreparePackages (1, NULL, FontPack); + mHii->NewPack (mHii, Package, &(Private->HiiHandle)); + FreePool (Package); + + // + // Free the font database + // + FreePool (FontPack); + + // + // If the current mode information can not be retrieved, then attemp to set the default mode + // of 800x600, 32 bit colot, 60 Hz refresh. + // + HorizontalResolution = 800; + VerticalResolution = 600; + + if (Private->GraphicsOutput != NULL) { + // + // The console is build on top of Graphics Output Protocol, find the mode number for 800x600 + // + for (ModeNumber = 0; ModeNumber < Private->GraphicsOutput->Mode->MaxMode; ModeNumber++) { + Status = Private->GraphicsOutput->QueryMode ( + Private->GraphicsOutput, + ModeNumber, + &SizeOfInfo, + &Info + ); + if (!EFI_ERROR (Status)) { + if ((Info->HorizontalResolution == 800) && + (Info->VerticalResolution == 600)) { + Status = Private->GraphicsOutput->SetMode (Private->GraphicsOutput, ModeNumber); + if (!EFI_ERROR (Status)) { + FreePool (Info); + break; + } + } + FreePool (Info); + } + } + + if (EFI_ERROR (Status) || (ModeNumber == Private->GraphicsOutput->Mode->MaxMode)) { + // + // Set default mode failed or device don't support default mode, then get the current mode information + // + HorizontalResolution = Private->GraphicsOutput->Mode->Info->HorizontalResolution; + VerticalResolution = Private->GraphicsOutput->Mode->Info->VerticalResolution; + ModeNumber = Private->GraphicsOutput->Mode->Mode; + } + } else { + // + // The console is build on top of UGA Draw Protocol + // + ColorDepth = 32; + RefreshRate = 60; + Status = Private->UgaDraw->SetMode ( + Private->UgaDraw, + HorizontalResolution, + VerticalResolution, + ColorDepth, + RefreshRate + ); + if (EFI_ERROR (Status)) { + // + // Get the current mode information from the UGA Draw Protocol + // + Status = Private->UgaDraw->GetMode ( + Private->UgaDraw, + &HorizontalResolution, + &VerticalResolution, + &ColorDepth, + &RefreshRate + ); + if (EFI_ERROR (Status)) { + goto Error; + } + } + } + + // + // Compute the maximum number of text Rows and Columns that this current graphics mode can support + // + Columns = HorizontalResolution / GLYPH_WIDTH; + Rows = VerticalResolution / GLYPH_HEIGHT; + + // + // See if the mode is too small to support the required 80x25 text mode + // + if (Columns < 80 || Rows < 25) { + goto Error; + } + // + // Add Mode #0 that must be 80x25 + // + MaxMode = 0; + Private->ModeData[MaxMode].GopWidth = HorizontalResolution; + Private->ModeData[MaxMode].GopHeight = VerticalResolution; + Private->ModeData[MaxMode].GopModeNumber = ModeNumber; + Private->ModeData[MaxMode].DeltaX = (HorizontalResolution - (80 * GLYPH_WIDTH)) >> 1; + Private->ModeData[MaxMode].DeltaY = (VerticalResolution - (25 * GLYPH_HEIGHT)) >> 1; + MaxMode++; + + // + // If it is possible to support Mode #1 - 80x50, than add it as an active mode + // + if (Rows >= 50) { + Private->ModeData[MaxMode].GopWidth = HorizontalResolution; + Private->ModeData[MaxMode].GopHeight = VerticalResolution; + Private->ModeData[MaxMode].GopModeNumber = ModeNumber; + Private->ModeData[MaxMode].DeltaX = (HorizontalResolution - (80 * GLYPH_WIDTH)) >> 1; + Private->ModeData[MaxMode].DeltaY = (VerticalResolution - (50 * GLYPH_HEIGHT)) >> 1; + MaxMode++; + } + // + // If the graphics mode is 800x600, than add a text mode that uses the entire display + // + if (HorizontalResolution == 800 && VerticalResolution == 600) { + + if (MaxMode < 2) { + Private->ModeData[MaxMode].Columns = 0; + Private->ModeData[MaxMode].Rows = 0; + Private->ModeData[MaxMode].GopWidth = 800; + Private->ModeData[MaxMode].GopHeight = 600; + Private->ModeData[MaxMode].GopModeNumber = ModeNumber; + Private->ModeData[MaxMode].DeltaX = 0; + Private->ModeData[MaxMode].DeltaY = 0; + MaxMode++; + } + + Private->ModeData[MaxMode].Columns = 800 / GLYPH_WIDTH; + Private->ModeData[MaxMode].Rows = 600 / GLYPH_HEIGHT; + Private->ModeData[MaxMode].GopWidth = 800; + Private->ModeData[MaxMode].GopHeight = 600; + Private->ModeData[MaxMode].GopModeNumber = ModeNumber; + Private->ModeData[MaxMode].DeltaX = (800 % GLYPH_WIDTH) >> 1; + Private->ModeData[MaxMode].DeltaY = (600 % GLYPH_HEIGHT) >> 1; + MaxMode++; + } + // + // Update the maximum number of modes + // + Private->SimpleTextOutputMode.MaxMode = (INT32) MaxMode; + + // + // Determine the number of text modes that this protocol can support + // + Status = GraphicsConsoleConOutSetMode (&Private->SimpleTextOutput, 0); + if (EFI_ERROR (Status)) { + goto Error; + } + + DEBUG_CODE_BEGIN (); + GraphicsConsoleConOutOutputString (&Private->SimpleTextOutput, (CHAR16 *)L"Graphics Console Started\n\r"); + DEBUG_CODE_END (); + + // + // Install protocol interfaces for the Graphics Console device. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiSimpleTextOutProtocolGuid, + &Private->SimpleTextOutput, + NULL + ); + +Error: + if (EFI_ERROR (Status)) { + // + // Close the GOP or UGA IO Protocol + // + if (Private->GraphicsOutput != NULL) { + gBS->CloseProtocol ( + Controller, + &gEfiGraphicsOutputProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else { + gBS->CloseProtocol ( + Controller, + &gEfiUgaDrawProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + + // + // Free private data + // + if (Private != NULL) { + if (Private->LineBuffer != NULL) { + FreePool (Private->LineBuffer); + } + FreePool (Private); + } + } + + return Status; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput; + GRAPHICS_CONSOLE_DEV *Private; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &SimpleTextOutput, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_STARTED; + } + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (SimpleTextOutput); + + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiSimpleTextOutProtocolGuid, + &Private->SimpleTextOutput + ); + + if (!EFI_ERROR (Status)) { + // + // Close the GOP or UGA IO Protocol + // + if (Private->GraphicsOutput != NULL) { + gBS->CloseProtocol ( + Controller, + &gEfiGraphicsOutputProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else { + gBS->CloseProtocol ( + Controller, + &gEfiUgaDrawProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + + // + // Remove the font pack + // + mHii->RemovePack (mHii, Private->HiiHandle); + + // + // Free our instance data + // + if (Private != NULL) { + FreePool (Private->LineBuffer); + FreePool (Private); + } + } + + return Status; +} + +EFI_STATUS +EfiLocateHiiProtocol ( + VOID + ) +/*++ + + Routine Description: + Find if the HII protocol is available. If yes, locate the HII protocol + + Arguments: + + Returns: + +--*/ +{ + EFI_HANDLE Handle; + UINTN Size; + EFI_STATUS Status; + + // + // There should only be one - so buffer size is this + // + Size = sizeof (EFI_HANDLE); + + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiHiiProtocolGuid, + NULL, + &Size, + &Handle + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->HandleProtocol ( + Handle, + &gEfiHiiProtocolGuid, + (VOID **)&mHii + ); + + return Status; +} +// +// Body of the STO functions +// +EFI_STATUS +EFIAPI +GraphicsConsoleConOutReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.Reset(). + If ExtendeVerification is TRUE, then perform dependent Graphics Console + device reset, and set display mode to mode 0. + If ExtendedVerification is FALSE, only set display mode to mode 0. + + Arguments: + + This - Indicates the calling context. + + ExtendedVerification - Indicates that the driver may perform a more exhaustive + verification operation of the device during reset. + + Returns: + + EFI_SUCCESS + The reset operation succeeds. + + EFI_DEVICE_ERROR + The Graphics Console is not functioning correctly + +--*/ +{ + This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)); + return This->SetMode (This, 0); +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.OutputString(). + The Unicode string will be converted to Glyphs and will be + sent to the Graphics Console. + + + Arguments: + + This - Indicates the calling context. + + WString - The Null-terminated Unicode string to be displayed on + the Graphics Console. + + Returns: + + EFI_SUCCESS + The string is output successfully. + + EFI_DEVICE_ERROR + The Graphics Console failed to send the string out. + + EFI_WARN_UNKNOWN_GLYPH + Indicates that some of the characters in the Unicode string could not + be rendered and are skipped. + +--*/ +{ + GRAPHICS_CONSOLE_DEV *Private; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + INTN Mode; + UINTN MaxColumn; + UINTN MaxRow; + UINTN Width; + UINTN Height; + UINTN Delta; + EFI_STATUS Status; + BOOLEAN Warning; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; + UINTN DeltaX; + UINTN DeltaY; + UINTN Count; + UINTN Index; + INT32 OriginAttribute; + EFI_TPL OldTpl; + CHAR16 SpaceStr[] = { NARROW_CHAR, ' ', 0 }; + + Status = EFI_SUCCESS; + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + // + // Current mode + // + Mode = This->Mode->Mode; + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + GraphicsOutput = Private->GraphicsOutput; + UgaDraw = Private->UgaDraw; + + MaxColumn = Private->ModeData[Mode].Columns; + MaxRow = Private->ModeData[Mode].Rows; + DeltaX = Private->ModeData[Mode].DeltaX; + DeltaY = Private->ModeData[Mode].DeltaY; + Width = MaxColumn * GLYPH_WIDTH; + Height = (MaxRow - 1) * GLYPH_HEIGHT; + Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + + // + // The Attributes won't change when during the time OutputString is called + // + GetTextColors (This, &Foreground, &Background); + + EraseCursor (This); + + Warning = FALSE; + + // + // Backup attribute + // + OriginAttribute = This->Mode->Attribute; + + while (*WString) { + + if (*WString == CHAR_BACKSPACE) { + // + // If the cursor is at the left edge of the display, then move the cursor + // one row up. + // + if (This->Mode->CursorColumn == 0 && This->Mode->CursorRow > 0) { + This->Mode->CursorRow--; + This->Mode->CursorColumn = (INT32) (MaxColumn - 1); + This->OutputString (This, SpaceStr); + EraseCursor (This); + This->Mode->CursorRow--; + This->Mode->CursorColumn = (INT32) (MaxColumn - 1); + } else if (This->Mode->CursorColumn > 0) { + // + // If the cursor is not at the left edge of the display, then move the cursor + // left one column. + // + This->Mode->CursorColumn--; + This->OutputString (This, SpaceStr); + EraseCursor (This); + This->Mode->CursorColumn--; + } + + WString++; + + } else if (*WString == CHAR_LINEFEED) { + // + // If the cursor is at the bottom of the display, then scroll the display one + // row, and do not update the cursor position. Otherwise, move the cursor + // down one row. + // + if (This->Mode->CursorRow == (INT32) (MaxRow - 1)) { + if (GraphicsOutput != NULL) { + // + // Scroll Screen Up One Row + // + GraphicsOutput->Blt ( + GraphicsOutput, + NULL, + EfiBltVideoToVideo, + DeltaX, + DeltaY + GLYPH_HEIGHT, + DeltaX, + DeltaY, + Width, + Height, + Delta + ); + + // + // Print Blank Line at last line + // + GraphicsOutput->Blt ( + GraphicsOutput, + &Background, + EfiBltVideoFill, + 0, + 0, + DeltaX, + DeltaY + Height, + Width, + GLYPH_HEIGHT, + Delta + ); + } else { + // + // Scroll Screen Up One Row + // + UgaDraw->Blt ( + UgaDraw, + NULL, + EfiUgaVideoToVideo, + DeltaX, + DeltaY + GLYPH_HEIGHT, + DeltaX, + DeltaY, + Width, + Height, + Delta + ); + + // + // Print Blank Line at last line + // + UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) (UINTN) &Background, + EfiUgaVideoFill, + 0, + 0, + DeltaX, + DeltaY + Height, + Width, + GLYPH_HEIGHT, + Delta + ); + } + } else { + This->Mode->CursorRow++; + } + + WString++; + + } else if (*WString == CHAR_CARRIAGE_RETURN) { + // + // Move the cursor to the beginning of the current row. + // + This->Mode->CursorColumn = 0; + WString++; + + } else if (*WString == WIDE_CHAR) { + + This->Mode->Attribute |= EFI_WIDE_ATTRIBUTE; + WString++; + + } else if (*WString == NARROW_CHAR) { + + This->Mode->Attribute &= (~ (UINT32) EFI_WIDE_ATTRIBUTE); + WString++; + + } else { + // + // Print the character at the current cursor position and move the cursor + // right one column. If this moves the cursor past the right edge of the + // display, then the line should wrap to the beginning of the next line. This + // is equivalent to inserting a CR and an LF. Note that if the cursor is at the + // bottom of the display, and the line wraps, then the display will be scrolled + // one line. + // If wide char is going to be displayed, need to display one character at a time + // Or, need to know the display length of a certain string. + // + // Index is used to determine how many character width units (wide = 2, narrow = 1) + // Count is used to determine how many characters are used regardless of their attributes + // + for (Count = 0, Index = 0; (This->Mode->CursorColumn + Index) < MaxColumn; Count++, Index++) { + if (WString[Count] == CHAR_NULL) { + break; + } + + if (WString[Count] == CHAR_BACKSPACE) { + break; + } + + if (WString[Count] == CHAR_LINEFEED) { + break; + } + + if (WString[Count] == CHAR_CARRIAGE_RETURN) { + break; + } + + if (WString[Count] == WIDE_CHAR) { + break; + } + + if (WString[Count] == NARROW_CHAR) { + break; + } + // + // Is the wide attribute on? + // + if (This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) { + // + // If wide, add one more width unit than normal since we are going to increment at the end of the for loop + // + Index++; + // + // This is the end-case where if we are at column 79 and about to print a wide character + // We should prevent this from happening because we will wrap inappropriately. We should + // not print this character until the next line. + // + if ((This->Mode->CursorColumn + Index + 1) > MaxColumn) { + Index++; + break; + } + } + } + + Status = DrawUnicodeWeightAtCursorN (This, WString, Count); + if (EFI_ERROR (Status)) { + Warning = TRUE; + } + // + // At the end of line, output carriage return and line feed + // + WString += Count; + This->Mode->CursorColumn += (INT32) Index; + if (This->Mode->CursorColumn > (INT32) MaxColumn) { + This->Mode->CursorColumn -= 2; + This->OutputString (This, SpaceStr); + } + + if (This->Mode->CursorColumn >= (INT32) MaxColumn) { + EraseCursor (This); + This->OutputString (This, mCrLfString); + EraseCursor (This); + } + } + } + + This->Mode->Attribute = OriginAttribute; + + EraseCursor (This); + + if (Warning) { + Status = EFI_WARN_UNKNOWN_GLYPH; + } + + gBS->RestoreTPL (OldTpl); + return Status; + +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.TestString(). + If one of the characters in the *Wstring is + neither valid valid Unicode drawing characters, + not ASCII code, then this function will return + EFI_UNSUPPORTED. + + + Arguments: + + This - Indicates the calling context. + + WString - The Null-terminated Unicode string to be tested. + + Returns: + + EFI_SUCCESS + The Graphics Console is capable of rendering the output string. + + EFI_UNSUPPORTED + Some of the characters in the Unicode string cannot be rendered. + +--*/ +{ + EFI_STATUS Status; + UINT16 GlyphWidth; + UINT32 GlyphStatus; + UINT16 Count; + GLYPH_UNION *Glyph; + + GlyphStatus = 0; + Count = 0; + + while (WString[Count]) { + Status = mHii->GetGlyph ( + mHii, + WString, + &Count, + (UINT8 **) &Glyph, + &GlyphWidth, + &GlyphStatus + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.QueryMode(). + It returnes information for an available text mode + that the Graphics Console supports. + In this driver,we only support text mode 80x25, which is + defined as mode 0. + + + Arguments: + + This - Indicates the calling context. + + ModeNumber - The mode number to return information on. + + Columns - The returned columns of the requested mode. + + Rows - The returned rows of the requested mode. + + Returns: + + EFI_SUCCESS + The requested mode information is returned. + + EFI_UNSUPPORTED + The mode number is not valid. + +--*/ +{ + GRAPHICS_CONSOLE_DEV *Private; + EFI_STATUS Status; + EFI_TPL OldTpl; + + if (ModeNumber >= (UINTN) This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + Status = EFI_SUCCESS; + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + + *Columns = Private->ModeData[ModeNumber].Columns; + *Rows = Private->ModeData[ModeNumber].Rows; + + if (*Columns <= 0 && *Rows <= 0) { + Status = EFI_UNSUPPORTED; + goto Done; + + } + +Done: + gBS->RestoreTPL (OldTpl); + return Status; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.SetMode(). + Set the Graphics Console to a specified mode. + In this driver, we only support mode 0. + + Arguments: + + This - Indicates the calling context. + + ModeNumber - The text mode to set. + + Returns: + + EFI_SUCCESS + The requested text mode is set. + + EFI_DEVICE_ERROR + The requested text mode cannot be set because of Graphics Console device error. + + EFI_UNSUPPORTED + The text mode number is not valid. + +--*/ +{ + EFI_STATUS Status; + GRAPHICS_CONSOLE_DEV *Private; + GRAPHICS_CONSOLE_MODE_DATA *ModeData; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewLineBuffer; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + UINT32 ColorDepth; + UINT32 RefreshRate; + EFI_TPL OldTpl; + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + GraphicsOutput = Private->GraphicsOutput; + UgaDraw = Private->UgaDraw; + ModeData = &(Private->ModeData[ModeNumber]); + + if (ModeData->Columns <= 0 && ModeData->Rows <= 0) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + // + // Make sure the requested mode number is supported + // + if (ModeNumber >= (UINTN) This->Mode->MaxMode) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + if (ModeData->Columns <= 0 && ModeData->Rows <= 0) { + Status = EFI_UNSUPPORTED; + goto Done; + } + // + // Attempt to allocate a line buffer for the requested mode number + // + NewLineBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ModeData->Columns * GLYPH_WIDTH * GLYPH_HEIGHT); + + if (NewLineBuffer == NULL) { + // + // The new line buffer could not be allocated, so return an error. + // No changes to the state of the current console have been made, so the current console is still valid + // + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + // + // If the mode has been set at least one other time, then LineBuffer will not be NULL + // + if (Private->LineBuffer != NULL) { + // + // Clear the current text window on the current graphics console + // + This->ClearScreen (This); + + // + // If the new mode is the same as the old mode, then just return EFI_SUCCESS + // + if ((INT32) ModeNumber == This->Mode->Mode) { + FreePool (NewLineBuffer); + Status = EFI_SUCCESS; + goto Done; + } + // + // Otherwise, the size of the text console and/or the UGA mode will be changed, + // so turn off the cursor, and free the LineBuffer for the current mode + // + This->EnableCursor (This, FALSE); + + FreePool (Private->LineBuffer); + } + // + // Assign the current line buffer to the newly allocated line buffer + // + Private->LineBuffer = NewLineBuffer; + + if (GraphicsOutput != NULL) { + if (ModeData->GopModeNumber != GraphicsOutput->Mode->Mode) { + // + // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode + // + Status = GraphicsOutput->SetMode (GraphicsOutput, ModeData->GopModeNumber); + if (EFI_ERROR (Status)) { + // + // The mode set operation failed + // + goto Done; + } + } else { + // + // The current graphics mode is correct, so simply clear the entire display + // + Status = GraphicsOutput->Blt ( + GraphicsOutput, + &mEfiColors[0], + EfiBltVideoFill, + 0, + 0, + 0, + 0, + ModeData->GopWidth, + ModeData->GopHeight, + 0 + ); + } + } else { + // + // Get the current UGA Draw mode information + // + Status = UgaDraw->GetMode ( + UgaDraw, + &HorizontalResolution, + &VerticalResolution, + &ColorDepth, + &RefreshRate + ); + if (EFI_ERROR (Status) || HorizontalResolution != ModeData->GopWidth || VerticalResolution != ModeData->GopHeight) { + // + // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode + // + Status = UgaDraw->SetMode ( + UgaDraw, + ModeData->GopWidth, + ModeData->GopHeight, + 32, + 60 + ); + if (EFI_ERROR (Status)) { + // + // The mode set operation failed + // + goto Done; + } + } else { + // + // The current graphics mode is correct, so simply clear the entire display + // + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) (UINTN) &mEfiColors[0], + EfiUgaVideoFill, + 0, + 0, + 0, + 0, + ModeData->GopWidth, + ModeData->GopHeight, + 0 + ); + } + } + + // + // The new mode is valid, so commit the mode change + // + This->Mode->Mode = (INT32) ModeNumber; + + // + // Move the text cursor to the upper left hand corner of the displat and enable it + // + This->SetCursorPosition (This, 0, 0); + This->EnableCursor (This, TRUE); + + Status = EFI_SUCCESS; + +Done: + gBS->RestoreTPL (OldTpl); + return Status; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.SetAttribute(). + + Arguments: + + This - Indicates the calling context. + + Attrubute - The attribute to set. Only bit0..6 are valid, all other bits + are undefined and must be zero. + + Returns: + + EFI_SUCCESS + The requested attribute is set. + + EFI_DEVICE_ERROR + The requested attribute cannot be set due to Graphics Console port error. + + EFI_UNSUPPORTED + The attribute requested is not defined by EFI spec. + +--*/ +{ + EFI_TPL OldTpl; + + if ((Attribute | 0xFF) != 0xFF) { + return EFI_UNSUPPORTED; + } + + if ((INT32) Attribute == This->Mode->Attribute) { + return EFI_SUCCESS; + } + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + EraseCursor (This); + + This->Mode->Attribute = (INT32) Attribute; + + EraseCursor (This); + + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.ClearScreen(). + It clears the Graphics Console's display to the + currently selected background color. + + + Arguments: + + This - Indicates the calling context. + + Returns: + + EFI_SUCCESS + The operation completed successfully. + + EFI_DEVICE_ERROR + The Graphics Console cannot be cleared due to Graphics Console device error. + + EFI_UNSUPPORTED + The Graphics Console is not in a valid text mode. + +--*/ +{ + EFI_STATUS Status; + GRAPHICS_CONSOLE_DEV *Private; + GRAPHICS_CONSOLE_MODE_DATA *ModeData; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; + EFI_TPL OldTpl; + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + GraphicsOutput = Private->GraphicsOutput; + UgaDraw = Private->UgaDraw; + ModeData = &(Private->ModeData[This->Mode->Mode]); + + GetTextColors (This, &Foreground, &Background); + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->Blt ( + GraphicsOutput, + &Background, + EfiBltVideoFill, + 0, + 0, + 0, + 0, + ModeData->GopWidth, + ModeData->GopHeight, + 0 + ); + } else { + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) (UINTN) &Background, + EfiUgaVideoFill, + 0, + 0, + 0, + 0, + ModeData->GopWidth, + ModeData->GopHeight, + 0 + ); + } + + This->Mode->CursorColumn = 0; + This->Mode->CursorRow = 0; + + EraseCursor (This); + + gBS->RestoreTPL (OldTpl); + + return Status; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition(). + + Arguments: + + This - Indicates the calling context. + + Column - The row to set cursor to. + + Row - The column to set cursor to. + + Returns: + + EFI_SUCCESS + The operation completed successfully. + + EFI_DEVICE_ERROR + The request fails due to Graphics Console device error. + + EFI_UNSUPPORTED + The Graphics Console is not in a valid text mode, or the cursor position + is invalid for current mode. + +--*/ +{ + GRAPHICS_CONSOLE_DEV *Private; + GRAPHICS_CONSOLE_MODE_DATA *ModeData; + EFI_STATUS Status; + EFI_TPL OldTpl; + + Status = EFI_SUCCESS; + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + ModeData = &(Private->ModeData[This->Mode->Mode]); + + if ((Column >= ModeData->Columns) || (Row >= ModeData->Rows)) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + if (((INT32) Column == This->Mode->CursorColumn) && ((INT32) Row == This->Mode->CursorRow)) { + Status = EFI_SUCCESS; + goto Done; + } + + EraseCursor (This); + + This->Mode->CursorColumn = (INT32) Column; + This->Mode->CursorRow = (INT32) Row; + + EraseCursor (This); + +Done: + gBS->RestoreTPL (OldTpl); + + return Status; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.EnableCursor(). + In this driver, the cursor cannot be hidden. + + Arguments: + + This - Indicates the calling context. + + Visible - If TRUE, the cursor is set to be visible, + If FALSE, the cursor is set to be invisible. + + Returns: + + EFI_SUCCESS + The request is valid. + + EFI_UNSUPPORTED + The Graphics Console does not support a hidden cursor. + +--*/ +{ + EFI_TPL OldTpl; + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + EraseCursor (This); + + This->Mode->CursorVisible = Visible; + + EraseCursor (This); + + gBS->RestoreTPL (OldTpl); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +GetTextColors ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground, + OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background + ) +{ + INTN Attribute; + + Attribute = This->Mode->Attribute & 0x7F; + + *Foreground = mEfiColors[Attribute & 0x0f]; + *Background = mEfiColors[Attribute >> 4]; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +DrawUnicodeWeightAtCursorN ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *UnicodeWeight, + IN UINTN Count + ) +{ + GRAPHICS_CONSOLE_DEV *Private; + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + GLYPH_UNION *Glyph; + GLYPH_UNION GlyphData; + INTN GlyphX; + INTN GlyphY; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; + UINTN Index; + UINTN ArrayIndex; + UINTN Counts; + UINT16 GlyphWidth; + UINT32 GlyphStatus; + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + + ReturnStatus = EFI_SUCCESS; + GlyphStatus = 0; + GlyphWidth = 0x08; + + GetTextColors (This, &Foreground, &Background); + + Index = 0; + ArrayIndex = 0; + while (Index < Count) { + if (This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) { + GlyphStatus = WIDE_CHAR; + } else { + GlyphStatus = NARROW_CHAR; + } + + Status = mHii->GetGlyph ( + mHii, + UnicodeWeight, + (UINT16 *) &Index, + (UINT8 **) &Glyph, + &GlyphWidth, + &GlyphStatus + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + + Counts = 0; + + CopyMem (&GlyphData, Glyph, sizeof (GLYPH_UNION)); + + do { + // + // We are creating the second half of the wide character's BLT buffer + // + if (GlyphWidth == 0x10 && Counts == 1) { + CopyMem (&GlyphData.NarrowGlyph.GlyphCol1, &Glyph->WideGlyph.GlyphCol2, sizeof (Glyph->WideGlyph.GlyphCol2)); + } + + Counts++; + + if (GlyphWidth == 0x10) { + mHii->GlyphToBlt ( + mHii, + (UINT8 *) &GlyphData, + Foreground, + Background, + Count * 2, + GLYPH_WIDTH, + GLYPH_HEIGHT, + &Private->LineBuffer[ArrayIndex * GLYPH_WIDTH] + ); + } else { + mHii->GlyphToBlt ( + mHii, + (UINT8 *) &GlyphData, + Foreground, + Background, + Count, + GLYPH_WIDTH, + GLYPH_HEIGHT, + &Private->LineBuffer[ArrayIndex * GLYPH_WIDTH] + ); + } + + ArrayIndex++; + + } while (Counts < 2 && GlyphWidth == 0x10); + + } + // + // If we are printing Wide characters, treat the BLT as if it is twice as many characters + // + if (GlyphWidth == 0x10) { + Count = Count * 2; + } + // + // Blt a character to the screen + // + GlyphX = This->Mode->CursorColumn * GLYPH_WIDTH; + GlyphY = This->Mode->CursorRow * GLYPH_HEIGHT; + GraphicsOutput = Private->GraphicsOutput; + UgaDraw = Private->UgaDraw; + if (GraphicsOutput != NULL) { + GraphicsOutput->Blt ( + GraphicsOutput, + Private->LineBuffer, + EfiBltBufferToVideo, + 0, + 0, + GlyphX + Private->ModeData[This->Mode->Mode].DeltaX, + GlyphY + Private->ModeData[This->Mode->Mode].DeltaY, + GLYPH_WIDTH * Count, + GLYPH_HEIGHT, + GLYPH_WIDTH * Count * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } else { + UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) (UINTN) Private->LineBuffer, + EfiUgaBltBufferToVideo, + 0, + 0, + GlyphX + Private->ModeData[This->Mode->Mode].DeltaX, + GlyphY + Private->ModeData[This->Mode->Mode].DeltaY, + GLYPH_WIDTH * Count, + GLYPH_HEIGHT, + GLYPH_WIDTH * Count * sizeof (EFI_UGA_PIXEL) + ); + } + + return ReturnStatus; +} + +STATIC +EFI_STATUS +EraseCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ) +{ + GRAPHICS_CONSOLE_DEV *Private; + EFI_SIMPLE_TEXT_OUTPUT_MODE *CurrentMode; + INTN GlyphX; + INTN GlyphY; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar[GLYPH_HEIGHT][GLYPH_WIDTH]; + UINTN X; + UINTN Y; + + CurrentMode = This->Mode; + + if (!CurrentMode->CursorVisible) { + return EFI_SUCCESS; + } + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + GraphicsOutput = Private->GraphicsOutput; + UgaDraw = Private->UgaDraw; + + // + // BUGBUG - we need to think about what to do with wide and narrow character deletions. + // + // + // Blt a character to the screen + // + GlyphX = (CurrentMode->CursorColumn * GLYPH_WIDTH) + Private->ModeData[CurrentMode->Mode].DeltaX; + GlyphY = (CurrentMode->CursorRow * GLYPH_HEIGHT) + Private->ModeData[CurrentMode->Mode].DeltaY; + if (GraphicsOutput != NULL) { + GraphicsOutput->Blt ( + GraphicsOutput, + (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar, + EfiBltVideoToBltBuffer, + GlyphX, + GlyphY, + 0, + 0, + GLYPH_WIDTH, + GLYPH_HEIGHT, + GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } else { + UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) (UINTN) BltChar, + EfiUgaVideoToBltBuffer, + GlyphX, + GlyphY, + 0, + 0, + GLYPH_WIDTH, + GLYPH_HEIGHT, + GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL) + ); + } + + GetTextColors (This, &Foreground.Pixel, &Background.Pixel); + + // + // Convert Monochrome bitmap of the Glyph to BltBuffer structure + // + for (Y = 0; Y < GLYPH_HEIGHT; Y++) { + for (X = 0; X < GLYPH_WIDTH; X++) { + if ((mCursorGlyph.GlyphCol1[Y] & (1 << X)) != 0) { + BltChar[Y][GLYPH_WIDTH - X - 1].Raw ^= Foreground.Raw; + } + } + } + + if (GraphicsOutput != NULL) { + GraphicsOutput->Blt ( + GraphicsOutput, + (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar, + EfiBltBufferToVideo, + 0, + 0, + GlyphX, + GlyphY, + GLYPH_WIDTH, + GLYPH_HEIGHT, + GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } else { + UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) (UINTN) BltChar, + EfiUgaBltBufferToVideo, + 0, + 0, + GlyphX, + GlyphY, + GLYPH_WIDTH, + GLYPH_HEIGHT, + GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL) + ); + } + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h new file mode 100644 index 0000000000..73daaa3b43 --- /dev/null +++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h @@ -0,0 +1,192 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GraphicsConsole.h + +Abstract: + + +Revision History + +--*/ + +#ifndef _GRAPHICS_CONSOLE_H +#define _GRAPHICS_CONSOLE_H + + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "ComponentName.h" + +// +// Glyph database +// +#define GLYPH_WIDTH 8 +#define GLYPH_HEIGHT 19 + +typedef union { + EFI_NARROW_GLYPH NarrowGlyph; + EFI_WIDE_GLYPH WideGlyph; +} GLYPH_UNION; + +extern EFI_NARROW_GLYPH UsStdNarrowGlyphData[]; +extern EFI_WIDE_GLYPH UsStdWideGlyphData[]; + +// +// Device Structure +// +#define GRAPHICS_CONSOLE_DEV_SIGNATURE EFI_SIGNATURE_32 ('g', 's', 't', 'o') + +typedef struct { + UINTN Columns; + UINTN Rows; + INTN DeltaX; + INTN DeltaY; + UINT32 GopWidth; + UINT32 GopHeight; + UINT32 GopModeNumber; +} GRAPHICS_CONSOLE_MODE_DATA; + +#define GRAPHICS_MAX_MODE 3 + +typedef struct { + UINTN Signature; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SimpleTextOutput; + EFI_SIMPLE_TEXT_OUTPUT_MODE SimpleTextOutputMode; + GRAPHICS_CONSOLE_MODE_DATA ModeData[GRAPHICS_MAX_MODE]; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LineBuffer; + EFI_HII_HANDLE HiiHandle; +} GRAPHICS_CONSOLE_DEV; + +#define GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS(a) \ + CR (a, GRAPHICS_CONSOLE_DEV, SimpleTextOutput, GRAPHICS_CONSOLE_DEV_SIGNATURE) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding; + +// +// Prototypes +// +UINTN +ReturnNarrowFontSize ( + VOID + ); + +UINTN +ReturnWideFontSize ( + VOID + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ); + +EFI_STATUS +EfiLocateHiiProtocol ( + VOID + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +#endif diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.inf b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.inf new file mode 100644 index 0000000000..441ee6338b --- /dev/null +++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.inf @@ -0,0 +1,110 @@ +#/** @file +# Component description file for GraphicsConsole module +# +# This is the main routine for initializing the Graphics Console support routines. +# Copyright (c) 2006 - 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = GraphicsConsole + FILE_GUID = CCCB0C28-4B24-11d5-9A5A-0090273FC14D + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + ENTRY_POINT = InitializeGraphicsConsole + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gGraphicsConsoleDriverBinding +# COMPONENT_NAME = gGraphicsConsoleComponentName +# + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ + +[Sources.common] + ComponentName.c + ComponentName.h + LaffStd.c + GraphicsConsole.c + GraphicsConsole.h + CommonHeader.h + EntryPoint.c + + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + + +################################################################################ +# +# Library Class Section - list of Library Classes that are required for +# this module. +# +################################################################################ + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + DebugLib + HiiLib + + +################################################################################ +# +# Guid C Name Section - list of Guids that this module uses or produces. +# +################################################################################ + +[Guids] + FontPack # ALWAYS_PRODUCED HII Formset + + +################################################################################ +# +# Protocol C Name Section - list of Protocol and Protocol Notify C Names +# that this module uses or produces. +# +################################################################################ + +[Protocols] + gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiSimpleTextOutProtocolGuid # PROTOCOL BY_START + gEfiHiiProtocolGuid # PROTOCOL TO_START + gEfiGraphicsOutputProtocolGuid # PROTOCOL TO_START + gEfiUgaDrawProtocolGuid # PROTOCOL TO_START + diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.msa b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.msa new file mode 100644 index 0000000000..187cc9b4ec --- /dev/null +++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.msa @@ -0,0 +1,92 @@ + + + + GraphicsConsole + DXE_DRIVER + CCCB0C28-4B24-11d5-9A5A-0090273FC14D + 1.0 + Component description file for GraphicsConsole module + This is the main routine for initializing the Graphics Console support routines. + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + GraphicsConsole + + + + DebugLib + Recommended libary Instance is PeiDxeDebugLibReportStatusCode instance in MdePkg. + + + UefiDriverModelLib + + + UefiDriverEntryPoint + + + UefiLib + + + HiiLib + + + BaseMemoryLib + + + MemoryAllocationLib + + + UefiBootServicesTableLib + + + + GraphicsConsole.h + GraphicsConsole.c + LaffStd.c + ComponentName.h + ComponentName.c + + + + + + + gEfiUgaDrawProtocolGuid + + + gEfiGraphicsOutputProtocolGuid + + + gEfiHiiProtocolGuid + + + gEfiSimpleTextOutProtocolGuid + + + gEfiDevicePathProtocolGuid + + + + + FontPack + Register UsStdNarrow Fonts into the global database. + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + gGraphicsConsoleDriverBinding + gGraphicsConsoleComponentName + + + \ No newline at end of file diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/LaffStd.c b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/LaffStd.c new file mode 100644 index 0000000000..d91f91fd89 --- /dev/null +++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/LaffStd.c @@ -0,0 +1,295 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + LaffStd.c + +Abstract: + + +Revision History + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "GraphicsConsole.h" + +EFI_NARROW_GLYPH UsStdNarrowGlyphData[] = { + // + // Unicode glyphs from 0x20 to 0x7e are the same as ASCII characters 0x20 to 0x7e + // + { 0x0020, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0021, 0x00, {0x00,0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}}, + { 0x0022, 0x00, {0x00,0x00,0x00,0x6C,0x6C,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0023, 0x00, {0x00,0x00,0x00,0x00,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00}}, + { 0x0024, 0x00, {0x00,0x00,0x18,0x18,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x18,0x18,0x00,0x00,0x00}}, + { 0x0025, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0x0C,0x0C,0x18,0x18,0x30,0x30,0x60,0x60,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x0026, 0x00, {0x00,0x00,0x00,0x78,0xCC,0xCC,0xCC,0x78,0x76,0xDC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x0027, 0x00, {0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0028, 0x00, {0x00,0x00,0x00,0x06,0x0C,0x0C,0x18,0x18,0x18,0x18,0x18,0x18,0x0C,0x0C,0x06,0x00,0x00,0x00,0x00}}, + { 0x0029, 0x00, {0x00,0x00,0x00,0xC0,0x60,0x60,0x30,0x30,0x30,0x30,0x30,0x30,0x60,0x60,0xC0,0x00,0x00,0x00,0x00}}, + { 0x002a, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x38,0xFE,0x38,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x002b, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x002c, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00}}, + { 0x002d, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x002e, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x002f, 0x00, {0x00,0x00,0x00,0x06,0x06,0x0C,0x0C,0x18,0x18,0x30,0x30,0x60,0x60,0xC0,0xC0,0x00,0x00,0x00,0x00}}, + { 0x0030, 0x00, {0x00,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00}}, + { 0x0031, 0x00, {0x00,0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00}}, + { 0x0032, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0x06,0x06,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC2,0xFE,0x00,0x00,0x00,0x00}}, + { 0x0033, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0x06,0x06,0x06,0x3C,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0034, 0x00, {0x00,0x00,0x00,0x1C,0x1C,0x3C,0x3C,0x6C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}}, + { 0x0035, 0x00, {0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0036, 0x00, {0x00,0x00,0x00,0x3C,0x60,0xC0,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0037, 0x00, {0x00,0x00,0x00,0xFE,0xC6,0x06,0x06,0x06,0x0C,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00}}, + { 0x0038, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0039, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00}}, + { 0x003a, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x003b, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00}}, + { 0x003c, 0x00, {0x00,0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0xC0,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00}}, + { 0x003d, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x003e, 0x00, {0x00,0x00,0x00,0x00,0xC0,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,0x00,0x00,0x00}}, + { 0x003f, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}}, + { 0x0040, 0x00, {0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0xC0,0x7E,0x00,0x00,0x00,0x00}}, + + { 0x0041, 0x00, {0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + + { 0x0042, 0x00, {0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00}}, + { 0x0043, 0x00, {0x00,0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00}}, + { 0x0044, 0x00, {0x00,0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00}}, + { 0x0045, 0x00, {0x00,0x00,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}}, + { 0x0046, 0x00, {0x00,0x00,0x00,0xFE,0x66,0x62,0x60,0x64,0x7C,0x64,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}}, + { 0x0047, 0x00, {0x00,0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xDE,0xC6,0xC6,0xC6,0x66,0x3C,0x00,0x00,0x00,0x00}}, + { 0x0048, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x0049, 0x00, {0x00,0x00,0x00,0xFC,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xFC,0x00,0x00,0x00,0x00}}, + { 0x004a, 0x00, {0x00,0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00}}, + { 0x004b, 0x00, {0x00,0x00,0x00,0xE6,0x66,0x6C,0x6C,0x78,0x70,0x78,0x6C,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}}, + { 0x004c, 0x00, {0x00,0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}}, + { 0x004d, 0x00, {0x00,0x00,0x00,0xC6,0xEE,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x004e, 0x00, {0x00,0x00,0x00,0xC6,0xE6,0xF6,0xF6,0xF6,0xDE,0xCE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x004f, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0050, 0x00, {0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}}, + { 0x0051, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0x7C,0x1C,0x0E,0x00,0x00}}, + { 0x0052, 0x00, {0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x7C,0x78,0x6C,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}}, + { 0x0053, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x60,0x38,0x0C,0x06,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0054, 0x00, {0x00,0x00,0x00,0xFC,0xFC,0xB4,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}}, + { 0x0055, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0056, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00}}, + { 0x0057, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00}}, + { 0x0058, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0xC6,0x6C,0x6C,0x38,0x6C,0x6C,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x0059, 0x00, {0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}}, + { 0x005a, 0x00, {0x00,0x00,0x00,0xFE,0xC6,0x86,0x0C,0x0C,0x18,0x30,0x60,0xC0,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00}}, + { 0x005b, 0x00, {0x00,0x00,0x00,0x1E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1E,0x00,0x00,0x00,0x00}}, + { 0x005c, 0x00, {0x00,0x00,0x00,0xC0,0xC0,0x60,0x60,0x30,0x30,0x18,0x18,0x0C,0x0C,0x06,0x06,0x00,0x00,0x00,0x00}}, + { 0x005d, 0x00, {0x00,0x00,0x00,0xF0,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xF0,0x00,0x00,0x00,0x00}}, + { 0x005e, 0x00, {0x00,0x00,0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x005f, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00}}, + { 0x0060, 0x00, {0x00,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0061, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x0062, 0x00, {0x00,0x00,0x00,0xE0,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0063, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0064, 0x00, {0x00,0x00,0x00,0x1C,0x0C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0xCC,0x7E,0x00,0x00,0x00,0x00}}, + { 0x0065, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0066, 0x00, {0x00,0x00,0x00,0x1E,0x33,0x30,0x30,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}}, + { 0x0067, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00}}, + { 0x0068, 0x00, {0x00,0x00,0x00,0xE0,0x60,0x60,0x60,0x7C,0x76,0x66,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}}, + { 0x0069, 0x00, {0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x006a, 0x00, {0x00,0x00,0x00,0x0C,0x0C,0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x6C,0x38,0x00}}, + { 0x006b, 0x00, {0x00,0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x70,0x78,0x6C,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00}}, + { 0x006c, 0x00, {0x00,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x006d, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEC,0xEE,0xFE,0xD6,0xD6,0xD6,0xD6,0xD6,0x00,0x00,0x00,0x00}}, + { 0x006e, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00}}, + { 0x006f, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0070, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00}}, + { 0x0071, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00}}, + { 0x0072, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x60,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}}, + { 0x0073, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0x7C,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0074, 0x00, {0x00,0x00,0x00,0x10,0x30,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00}}, + { 0x0075, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x0076, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x00,0x00,0x00,0x00}}, + { 0x0077, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00}}, + { 0x0078, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x6C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x0079, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00}}, + { 0x007a, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x86,0x0C,0x18,0x30,0x60,0xC0,0xFE,0x00,0x00,0x00,0x00}}, + { 0x007b, 0x00, {0x00,0x00,0x00,0x0E,0x18,0x18,0x18,0x18,0x30,0x18,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00}}, + { 0x007c, 0x00, {0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00}}, + { 0x007d, 0x00, {0x00,0x00,0x00,0xE0,0x30,0x30,0x30,0x30,0x18,0x30,0x30,0x30,0x30,0x30,0xE0,0x00,0x00,0x00,0x00}}, + { 0x007e, 0x00, {0x00,0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + + { 0x00a0, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00a1, 0x00, {0x00,0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00}}, + { 0x00a2, 0x00, {0x00,0x00,0x00,0x00,0x18,0x18,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x18,0x18,0x00,0x00,0x00,0x00}}, + { 0x00a3, 0x00, {0x00,0x00,0x00,0x38,0x6C,0x64,0x60,0x60,0xF0,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00}}, + { 0x00a4, 0x00, {0x00,0x00,0x18,0x00,0x00,0x00,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x00a5, 0x00, {0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00}}, + { 0x00a6, 0x00, {0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00}}, + { 0x00a7, 0x00, {0x00,0x00,0x18,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00a8, 0x00, {0x00,0x00,0x00,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00a9, 0x00, {0x00,0x00,0x00,0x00,0x7C,0x82,0x9A,0xA2,0xA2,0xA2,0x9A,0x82,0x7C,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00aa, 0x00, {0x00,0x00,0x00,0x00,0x3C,0x6C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ab, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ac, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ad, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ae, 0x00, {0x00,0x00,0x00,0x00,0x7C,0x82,0xB2,0xAA,0xAA,0xB2,0xAA,0xAA,0x82,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00af, 0x00, {0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b0, 0x00, {0x00,0x00,0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b1, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b2, 0x00, {0x00,0x00,0x00,0x3C,0x66,0x0C,0x18,0x32,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b3, 0x00, {0x00,0x00,0x00,0x7C,0x06,0x3C,0x06,0x06,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b4, 0x00, {0x00,0x00,0x00,0x0C,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b5, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xC0,0x00}}, + { 0x00b6, 0x00, {0x00,0x00,0x00,0x7F,0xDB,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00}}, + { 0x00b7, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b8, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0x78,0x00,0x00,0x00}}, + { 0x00b9, 0x00, {0x00,0x00,0x00,0x18,0x38,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ba, 0x00, {0x00,0x00,0x00,0x00,0x38,0x6C,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00bb, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00bc, 0x00, {0x00,0x00,0x00,0x60,0xE0,0x62,0x66,0x6C,0x18,0x30,0x66,0xCE,0x9A,0x3F,0x06,0x06,0x00,0x00,0x00}}, + { 0x00bd, 0x00, {0x00,0x00,0x00,0x60,0xE0,0x62,0x66,0x6C,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00,0x00}}, + { 0x00be, 0x00, {0x00,0x00,0x00,0xE0,0x30,0x62,0x36,0xEC,0x18,0x30,0x66,0xCE,0x9A,0x3F,0x06,0x06,0x00,0x00,0x00}}, + { 0x00bf, 0x00, {0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00c0, 0x00, {0x60,0x30,0x18,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x00c1, 0x00, {0x18,0x30,0x60,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x00c2, 0x00, {0x10,0x38,0x6C,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x00c3, 0x00, {0x76,0xDC,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x00c4, 0x00, {0xCC,0xCC,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x00c5, 0x00, {0x38,0x6C,0x38,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x00c6, 0x00, {0x00,0x00,0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00}}, + { 0x00c7, 0x00, {0x00,0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x18,0x70,0x00,0x00}}, + { 0x00c8, 0x00, {0x60,0x30,0x18,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}}, + { 0x00c9, 0x00, {0x18,0x30,0x60,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}}, + { 0x00ca, 0x00, {0x10,0x38,0x6C,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}}, + { 0x00cb, 0x00, {0xCC,0xCC,0x00,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}}, + { 0x00cc, 0x00, {0x60,0x30,0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00cd, 0x00, {0x18,0x30,0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00ce, 0x00, {0x10,0x38,0x6C,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00cf, 0x00, {0xCC,0xCC,0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00d0, 0x00, {0x00,0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0xF6,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00}}, + { 0x00d1, 0x00, {0x76,0xDC,0x00,0x00,0xC6,0xE6,0xE6,0xF6,0xF6,0xDE,0xDE,0xCE,0xCE,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x00d2, 0x00, {0x60,0x30,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00d3, 0x00, {0x18,0x30,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00d4, 0x00, {0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00d5, 0x00, {0x76,0xDC,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00d6, 0x00, {0xCC,0xCC,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00d7, 0x00, {0x10,0x28,0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x6C,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x00d8, 0x00, {0x00,0x00,0x00,0x7C,0xCE,0xCE,0xDE,0xD6,0xD6,0xD6,0xD6,0xF6,0xE6,0xE6,0x7C,0x40,0x00,0x00,0x00}}, + { 0x00d9, 0x00, {0x60,0x30,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00da, 0x00, {0x18,0x30,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00db, 0x00, {0x10,0x38,0x6C,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00dc, 0x00, {0xCC,0xCC,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00dd, 0x00, {0x18,0x30,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00de, 0x00, {0x00,0x00,0x10,0x00,0xF0,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x60,0xF0,0x00,0x00,0x00,0x00}}, + { 0x00df, 0x00, {0x00,0x00,0x00,0x78,0xCC,0xCC,0xCC,0xCC,0xD8,0xCC,0xC6,0xC6,0xC6,0xC6,0xCC,0x00,0x00,0x00,0x00}}, + { 0x00e0, 0x00, {0x00,0x30,0x30,0x60,0x30,0x18,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00e1, 0x00, {0x00,0x00,0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00e2, 0x00, {0x00,0x00,0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00e3, 0x00, {0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00e4, 0x00, {0x00,0x00,0x00,0xCC,0xCC,0x00,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00e5, 0x00, {0x00,0x00,0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00e6, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEC,0x36,0x36,0x7E,0xD8,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00}}, + { 0x00e7, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC0,0xC6,0x7C,0x18,0x70,0x00,0x00}}, + { 0x00e8, 0x00, {0x00,0x00,0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00e9, 0x00, {0x00,0x00,0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00ea, 0x00, {0x00,0x00,0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00eb, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00ec, 0x00, {0x00,0x00,0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00ed, 0x00, {0x00,0x00,0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00ee, 0x00, {0x00,0x00,0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00ef, 0x00, {0x00,0x00,0x00,0x66,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00f0, 0x00, {0x00,0x00,0x00,0x34,0x18,0x2C,0x0C,0x06,0x3E,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00f1, 0x00, {0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00}}, + { 0x00f2, 0x00, {0x00,0x00,0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00f3, 0x00, {0x00,0x00,0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00f4, 0x00, {0x00,0x00,0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00f5, 0x00, {0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00f6, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00f7, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00f8, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xCE,0xDE,0xD6,0xF6,0xE6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00f9, 0x00, {0x00,0x00,0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00fa, 0x00, {0x00,0x00,0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00fb, 0x00, {0x00,0x00,0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00fc, 0x00, {0x00,0x00,0x00,0xCC,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00fd, 0x00, {0x00,0x00,0x00,0x0C,0x18,0x30,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00}}, + { 0x00fe, 0x00, {0x00,0x00,0x00,0xE0,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00}}, + { 0x00ff, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00}}, + + { (CHAR16)BOXDRAW_HORIZONTAL, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_VERTICAL, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_DOWN_RIGHT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_DOWN_LEFT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_UP_RIGHT, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_UP_LEFT, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_VERTICAL_RIGHT, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_VERTICAL_LEFT, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_DOWN_HORIZONTAL, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_UP_HORIZONTAL, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_VERTICAL_HORIZONTAL, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_DOUBLE_HORIZONTAL, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_DOUBLE_VERTICAL, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOWN_RIGHT_DOUBLE, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_DOWN_DOUBLE_RIGHT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOUBLE_DOWN_RIGHT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOWN_LEFT_DOUBLE, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_DOWN_DOUBLE_LEFT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOUBLE_DOWN_LEFT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_UP_RIGHT_DOUBLE, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_UP_DOUBLE_RIGHT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_DOUBLE_UP_RIGHT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_UP_LEFT_DOUBLE, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_UP_DOUBLE_LEFT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_DOUBLE_UP_LEFT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_VERTICAL_RIGHT_DOUBLE, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_VERTICAL_DOUBLE_RIGHT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOUBLE_VERTICAL_RIGHT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_VERTICAL_LEFT_DOUBLE, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_VERTICAL_DOUBLE_LEFT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOUBLE_VERTICAL_LEFT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOWN_HORIZONTAL_DOUBLE, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_DOWN_DOUBLE_HORIZONTAL, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOUBLE_DOWN_HORIZONTAL, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_UP_HORIZONTAL_DOUBLE, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_UP_DOUBLE_HORIZONTAL, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_DOUBLE_UP_HORIZONTAL, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + + { (CHAR16)BLOCKELEMENT_FULL_BLOCK, 0x00, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}, + { (CHAR16)BLOCKELEMENT_LIGHT_SHADE, 0x00, {0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22}}, + + { (CHAR16)GEOMETRICSHAPE_RIGHT_TRIANGLE, 0x00, {0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)GEOMETRICSHAPE_LEFT_TRIANGLE, 0x00, {0x00,0x00,0x00,0x00,0x00,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)GEOMETRICSHAPE_UP_TRIANGLE, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)GEOMETRICSHAPE_DOWN_TRIANGLE, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00}}, + + { (CHAR16)ARROW_UP, 0x00, {0x00,0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)ARROW_DOWN, 0x00, {0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)ARROW_LEFT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x20,0x60,0x60,0xFE,0xFE,0x60,0x60,0x20,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)ARROW_RIGHT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x08,0x0C,0x0C,0xFE,0xFE,0x0C,0x0C,0x08,0x00,0x00,0x00,0x00,0x00,0x00}}, + + { 0x0000, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} //EOL +}; + +UINTN +ReturnNarrowFontSize ( + VOID + ) +{ + // + // I need the size of this outside of this file, so here is a stub function to do that for me + // + return sizeof (UsStdNarrowGlyphData); +} diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/CommonHeader.h b/MdeModulePkg/Universal/Console/TerminalDxe/CommonHeader.h new file mode 100644 index 0000000000..7aca138d4e --- /dev/null +++ b/MdeModulePkg/Universal/Console/TerminalDxe/CommonHeader.h @@ -0,0 +1,51 @@ +/**@file + Common header file shared by all source files. + + This file includes package header files, library classes and protocol, PPI & GUID definitions. + + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + + +// +// The package level header files this module uses +// +#include +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +// +// Driver Binding Externs +// +extern EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gTerminalComponentName; + +#endif diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/ComponentName.c b/MdeModulePkg/Universal/Console/TerminalDxe/ComponentName.c new file mode 100644 index 0000000000..9048326f5a --- /dev/null +++ b/MdeModulePkg/Universal/Console/TerminalDxe/ComponentName.c @@ -0,0 +1,200 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "Terminal.h" + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gTerminalComponentName = { + TerminalComponentNameGetDriverName, + TerminalComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mTerminalDriverNameTable[] = { + { + "eng", + (CHAR16 *) L"Serial Terminal Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +TerminalComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gTerminalComponentName.SupportedLanguages, + mTerminalDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +TerminalComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput; + TERMINAL_DEV *TerminalDevice; + + // + // Make sure this driver is currently managing ControllHandle + // + Status = EfiTestManagedDevice ( + ControllerHandle, + gTerminalDriverBinding.DriverBindingHandle, + &gEfiSerialIoProtocolGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // This is a bus driver, so ChildHandle can not be NULL. + // + if (ChildHandle == NULL) { + return EFI_UNSUPPORTED; + } + + Status = EfiTestChildHandle ( + ControllerHandle, + ChildHandle, + &gEfiSerialIoProtocolGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get our context back + // + Status = gBS->OpenProtocol ( + ChildHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &SimpleTextOutput, + gTerminalDriverBinding.DriverBindingHandle, + ChildHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput); + + return LookupUnicodeString ( + Language, + gTerminalComponentName.SupportedLanguages, + TerminalDevice->ControllerNameTable, + ControllerName + ); +} diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/EntryPoint.c b/MdeModulePkg/Universal/Console/TerminalDxe/EntryPoint.c new file mode 100644 index 0000000000..a8feebb1d1 --- /dev/null +++ b/MdeModulePkg/Universal/Console/TerminalDxe/EntryPoint.c @@ -0,0 +1,56 @@ +/**@file + Entry Point Source file. + + This file contains the user entry point + + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +/** + The user Entry Point for module Terminal. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeTerminal( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gTerminalDriverBinding, + ImageHandle, + &gTerminalComponentName, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + + return Status; +} diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c new file mode 100644 index 0000000000..01ab587bd6 --- /dev/null +++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c @@ -0,0 +1,1194 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Terminal.c + +Abstract: + +Revision History: + +--*/ + + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "Terminal.h" + +#include "FrameworkDxe.h" + +// +// Globals +// +EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding = { + TerminalDriverBindingSupported, + TerminalDriverBindingStart, + TerminalDriverBindingStop, + 0xa, + NULL, + NULL +}; + + +EFI_STATUS +EFIAPI +TerminalDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + VENDOR_DEVICE_PATH *Node; + + // + // If remaining device path is not NULL, then make sure it is a + // device path that describes a terminal communications protocol. + // + if (RemainingDevicePath != NULL) { + + Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath; + + if (Node->Header.Type != MESSAGING_DEVICE_PATH || + Node->Header.SubType != MSG_VENDOR_DP || + DevicePathNodeLength(&Node->Header) != sizeof(VENDOR_DEVICE_PATH)) { + + return EFI_UNSUPPORTED; + + } + // + // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types + // + if (!CompareGuid (&Node->Guid, &gEfiPcAnsiGuid) && + !CompareGuid (&Node->Guid, &gEfiVT100Guid) && + !CompareGuid (&Node->Guid, &gEfiVT100PlusGuid) && + !CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) { + + return EFI_UNSUPPORTED; + } + } + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // The Controller must support the Serial I/O Protocol. + // This driver is a bus driver with at most 1 child device, so it is + // ok for it to be already started. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSerialIoProtocolGuid, + (VOID **) &SerialIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Controller, + &gEfiSerialIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +EFI_STATUS +EFIAPI +TerminalDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Start the controller. + + Arguments: + + This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + Controller - The handle of the controller to start. + RemainingDevicePath - A pointer to the remaining portion of a devcie path. + + Returns: + + EFI_SUCCESS. + +--*/ +{ + EFI_STATUS Status; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + VENDOR_DEVICE_PATH *Node; + VENDOR_DEVICE_PATH *DefaultNode; + EFI_SERIAL_IO_MODE *Mode; + UINTN SerialInTimeOut; + TERMINAL_DEV *TerminalDevice; + UINT8 TerminalType; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + UINTN EntryCount; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + TerminalDevice = NULL; + DefaultNode = NULL; + // + // Get the Device Path Protocol to build the device path of the child device + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + // + // Report that the remote terminal is being enabled + // + DevicePath = ParentDevicePath; + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_ENABLE, + DevicePath + ); + + // + // Open the Serial I/O Protocol BY_DRIVER. It might already be started. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSerialIoProtocolGuid, + (VOID **) &SerialIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + + if (Status != EFI_ALREADY_STARTED) { + // + // If Serial I/O is not already open by this driver, then tag the handle + // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and + // StdErrDev variables with the list of possible terminal types on this + // serial port. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiCallerIdGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiCallerIdGuid, + DuplicateDevicePath (ParentDevicePath), + NULL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + // + // if the serial device is a hot plug device, do not update the + // ConInDev, ConOutDev, and StdErrDev variables. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiHotPlugDeviceGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + TerminalUpdateConsoleDevVariable ((CHAR16 *)VarConsoleInpDev, ParentDevicePath); + TerminalUpdateConsoleDevVariable ((CHAR16 *)VarConsoleOutDev, ParentDevicePath); + TerminalUpdateConsoleDevVariable ((CHAR16 *)VarErrorOutDev, ParentDevicePath); + } + } + } + // + // Make sure a child handle does not already exist. This driver can only + // produce one child per serial port. + // + Status = gBS->OpenProtocolInformation ( + Controller, + &gEfiSerialIoProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (!EFI_ERROR (Status)) { + Status = EFI_SUCCESS; + for (Index = 0; Index < EntryCount; Index++) { + if (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) { + Status = EFI_ALREADY_STARTED; + } + } + + FreePool (OpenInfoBuffer); + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // If RemainingDevicePath is NULL, then create default device path node + // + if (RemainingDevicePath == NULL) { + DefaultNode = AllocatePool (sizeof (VENDOR_DEVICE_PATH)); + if (DefaultNode == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + + CopyMem (&DefaultNode->Guid, &gEfiPcAnsiGuid, sizeof (EFI_GUID)); + RemainingDevicePath = (EFI_DEVICE_PATH_PROTOCOL*) DefaultNode; + } + // + // Use the RemainingDevicePath to determine the terminal type + // + Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath; + + if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) { + + TerminalType = PcAnsiType; + + } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) { + + TerminalType = VT100Type; + + } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) { + + TerminalType = VT100PlusType; + + } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) { + + TerminalType = VTUTF8Type; + + } else { + goto Error; + } + // + // Initialize the Terminal Dev + // + TerminalDevice = AllocatePool (sizeof (TERMINAL_DEV)); + if (TerminalDevice == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + + ZeroMem (TerminalDevice, sizeof (TERMINAL_DEV)); + + TerminalDevice->Signature = TERMINAL_DEV_SIGNATURE; + + TerminalDevice->TerminalType = TerminalType; + + TerminalDevice->SerialIo = SerialIo; + + // + // Simple Input Protocol + // + TerminalDevice->SimpleInput.Reset = TerminalConInReset; + TerminalDevice->SimpleInput.ReadKeyStroke = TerminalConInReadKeyStroke; + + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + TerminalConInWaitForKey, + &TerminalDevice->SimpleInput, + &TerminalDevice->SimpleInput.WaitForKey + ); + if (EFI_ERROR (Status)) { + goto Error; + } + // + // initialize the FIFO buffer used for accommodating + // the pre-read pending characters + // + InitializeRawFiFo (TerminalDevice); + InitializeUnicodeFiFo (TerminalDevice); + InitializeEfiKeyFiFo (TerminalDevice); + + // + // Set the timeout value of serial buffer for + // keystroke response performance issue + // + Mode = TerminalDevice->SerialIo->Mode; + + SerialInTimeOut = 0; + if (Mode->BaudRate != 0) { + SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate; + } + + Status = TerminalDevice->SerialIo->SetAttributes ( + TerminalDevice->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)) { + // + // if set attributes operation fails, invalidate + // the value of SerialInTimeOut,thus make it + // inconsistent with the default timeout value + // of serial buffer. This will invoke the recalculation + // in the readkeystroke routine. + // + TerminalDevice->SerialInTimeOut = 0; + } else { + TerminalDevice->SerialInTimeOut = SerialInTimeOut; + } + // + // Build the device path for the child device + // + Status = SetTerminalDevicePath ( + TerminalDevice->TerminalType, + ParentDevicePath, + &TerminalDevice->DevicePath + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + DevicePath = TerminalDevice->DevicePath; + + Status = TerminalDevice->SimpleInput.Reset ( + &TerminalDevice->SimpleInput, + FALSE + ); + if (EFI_ERROR (Status)) { + // + // Need to report Error Code first + // + goto ReportError; + } + // + // Simple Text Output Protocol + // + TerminalDevice->SimpleTextOutput.Reset = TerminalConOutReset; + TerminalDevice->SimpleTextOutput.OutputString = TerminalConOutOutputString; + TerminalDevice->SimpleTextOutput.TestString = TerminalConOutTestString; + TerminalDevice->SimpleTextOutput.QueryMode = TerminalConOutQueryMode; + TerminalDevice->SimpleTextOutput.SetMode = TerminalConOutSetMode; + TerminalDevice->SimpleTextOutput.SetAttribute = TerminalConOutSetAttribute; + TerminalDevice->SimpleTextOutput.ClearScreen = TerminalConOutClearScreen; + TerminalDevice->SimpleTextOutput.SetCursorPosition = TerminalConOutSetCursorPosition; + TerminalDevice->SimpleTextOutput.EnableCursor = TerminalConOutEnableCursor; + TerminalDevice->SimpleTextOutput.Mode = &TerminalDevice->SimpleTextOutputMode; + + TerminalDevice->SimpleTextOutputMode.MaxMode = 1; + // + // For terminal devices, cursor is always visible + // + TerminalDevice->SimpleTextOutputMode.CursorVisible = TRUE; + TerminalDevice->SimpleTextOutputMode.Attribute = EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK); + + Status = TerminalDevice->SimpleTextOutput.Reset ( + &TerminalDevice->SimpleTextOutput, + FALSE + ); + if (EFI_ERROR (Status)) { + goto ReportError; + } + + Status = TerminalDevice->SimpleTextOutput.SetMode ( + &TerminalDevice->SimpleTextOutput, + 0 + ); + if (EFI_ERROR (Status)) { + goto ReportError; + } + + Status = TerminalDevice->SimpleTextOutput.EnableCursor ( + &TerminalDevice->SimpleTextOutput, + TRUE + ); + if (EFI_ERROR (Status)) { + goto ReportError; + } + // + // + // + TerminalDevice->InputState = INPUT_STATE_DEFAULT; + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + + Status = gBS->CreateEvent ( + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &TerminalDevice->TwoSecondTimeOut + ); + + // + // Build the component name for the child device + // + TerminalDevice->ControllerNameTable = NULL; + switch (TerminalDevice->TerminalType) { + case PcAnsiType: + AddUnicodeString ( + "eng", + gTerminalComponentName.SupportedLanguages, + &TerminalDevice->ControllerNameTable, + (CHAR16 *)L"PC-ANSI Serial Console" + ); + break; + + case VT100Type: + AddUnicodeString ( + "eng", + gTerminalComponentName.SupportedLanguages, + &TerminalDevice->ControllerNameTable, + (CHAR16 *)L"VT-100 Serial Console" + ); + break; + + case VT100PlusType: + AddUnicodeString ( + "eng", + gTerminalComponentName.SupportedLanguages, + &TerminalDevice->ControllerNameTable, + (CHAR16 *)L"VT-100+ Serial Console" + ); + break; + + case VTUTF8Type: + AddUnicodeString ( + "eng", + gTerminalComponentName.SupportedLanguages, + &TerminalDevice->ControllerNameTable, + (CHAR16 *)L"VT-UTF8 Serial Console" + ); + break; + } + // + // Install protocol interfaces for the serial device. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &TerminalDevice->Handle, + &gEfiDevicePathProtocolGuid, + TerminalDevice->DevicePath, + &gEfiSimpleTextInProtocolGuid, + &TerminalDevice->SimpleInput, + &gEfiSimpleTextOutProtocolGuid, + &TerminalDevice->SimpleTextOutput, + NULL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + // + // if the serial device is a hot plug device, attaches the HotPlugGuid + // onto the terminal device handle. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiHotPlugDeviceGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &TerminalDevice->Handle, + &gEfiHotPlugDeviceGuid, + NULL, + NULL + ); + } + // + // Register the Parent-Child relationship via + // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSerialIoProtocolGuid, + (VOID **) &TerminalDevice->SerialIo, + This->DriverBindingHandle, + TerminalDevice->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + if (DefaultNode != NULL) { + FreePool (DefaultNode); + } + + return EFI_SUCCESS; + +ReportError: + // + // Report error code before exiting + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, + DevicePath + ); + +Error: + // + // Use the Stop() function to free all resources allocated in Start() + // + if (TerminalDevice != NULL) { + + if (TerminalDevice->Handle != NULL) { + This->Stop (This, Controller, 1, &TerminalDevice->Handle); + } else { + + if (TerminalDevice->TwoSecondTimeOut != NULL) { + gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut); + } + + if (TerminalDevice->SimpleInput.WaitForKey != NULL) { + gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey); + } + + if (TerminalDevice->ControllerNameTable != NULL) { + FreeUnicodeStringTable (TerminalDevice->ControllerNameTable); + } + + if (TerminalDevice->DevicePath != NULL) { + FreePool (TerminalDevice->DevicePath); + } + + FreePool (TerminalDevice); + } + } + + if (DefaultNode != NULL) { + FreePool (DefaultNode); + } + + This->Stop (This, Controller, 0, NULL); + + return Status; +} + +EFI_STATUS +EFIAPI +TerminalDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + + Stop a device controller. + + Arguments: + + This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + Controller - A handle to the device being stopped. + NumberOfChildren - The number of child device handles in ChildHandleBuffer. + ChildHandleBuffer - An array of child handles to be freed. + + Returns: + + EFI_SUCCESS - Operation successful. + EFI_DEVICE_ERROR - Devices error. + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + BOOLEAN AllChildrenStopped; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput; + TERMINAL_DEV *TerminalDevice; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status = gBS->HandleProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Report that the remote terminal is being disabled + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_DISABLE, + DevicePath + ); + + // + // 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 ( + Controller, + &gEfiCallerIdGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + // + // Remove Parent Device Path from + // the Console Device Environment Variables + // + TerminalRemoveConsoleDevVariable ((CHAR16 *)VarConsoleInpDev, ParentDevicePath); + TerminalRemoveConsoleDevVariable ((CHAR16 *)VarConsoleOutDev, ParentDevicePath); + TerminalRemoveConsoleDevVariable ((CHAR16 *)VarErrorOutDev, ParentDevicePath); + + // + // Uninstall the Terminal Driver's GUID Tag from the Serial controller + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiCallerIdGuid, + ParentDevicePath, + NULL + ); + + // + // Free the ParentDevicePath that was duplicated in Start() + // + if (!EFI_ERROR (Status)) { + FreePool (ParentDevicePath); + } + } + + gBS->CloseProtocol ( + Controller, + &gEfiSerialIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; + } + + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + + Status = gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &SimpleTextOutput, + This->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput); + + gBS->CloseProtocol ( + Controller, + &gEfiSerialIoProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Index], + &gEfiSimpleTextInProtocolGuid, + &TerminalDevice->SimpleInput, + &gEfiSimpleTextOutProtocolGuid, + &TerminalDevice->SimpleTextOutput, + &gEfiDevicePathProtocolGuid, + TerminalDevice->DevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + Controller, + &gEfiSerialIoProtocolGuid, + (VOID **) &SerialIo, + This->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + + if (TerminalDevice->ControllerNameTable != NULL) { + FreeUnicodeStringTable (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); + FreePool (TerminalDevice->DevicePath); + 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 = AppendDevicePathInstance (Variable, TempDevicePath); + if (Variable != NULL) { + FreePool (Variable); + } + + if (TempDevicePath != NULL) { + FreePool (TempDevicePath); + } + + Variable = NewVariable; + } + + VariableSize = GetDevicePathSize (Variable); + + Status = gRT->SetVariable ( + VariableName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + VariableSize, + Variable + ); + ASSERT_EFI_ERROR (Status); + FreePool (Variable); + + return ; +} + +VOID +TerminalRemoveConsoleDevVariable ( + IN CHAR16 *VariableName, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath + ) +/*++ + + Routine Description: + + Remove console device variable. + + Arguments: + + VariableName - A pointer to the variable name. + ParentDevicePath - A pointer to the parent device path. + + Returns: + +--*/ +{ + 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 = GetNextDevicePathInstance (&Variable, &InstanceSize); + if (Instance == NULL) { + 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 (CompareMem (Instance, TempDevicePath, InstanceSize) == 0) { + Match = TRUE; + FoundOne = TRUE; + } + + FreePool (TempDevicePath); + } + } + // + // If a match was not found, then keep the current device path instance + // + if (!Match) { + SavedNewVariable = NewVariable; + NewVariable = AppendDevicePathInstance (NewVariable, Instance); + if (SavedNewVariable != NULL) { + FreePool (SavedNewVariable); + } + } + // + // Get next device path instance from Variable + // + FreePool (Instance); + Instance = GetNextDevicePathInstance (&Variable, &InstanceSize); + } while (Instance != NULL); + + FreePool (OriginalVariable); + + if (FoundOne) { + VariableSize = GetDevicePathSize (NewVariable); + + Status = gRT->SetVariable ( + VariableName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + VariableSize, + NewVariable + ); + ASSERT_EFI_ERROR (Status); + } + + if (NewVariable != NULL) { + FreePool (NewVariable); + } + + return ; +} + +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; + Buffer = AllocatePool (BufferSize); + if (Buffer == NULL) { + *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 + // + FreePool (Buffer); + Buffer = AllocatePool (BufferSize); + if (Buffer == NULL) { + *VariableSize = 0; + return NULL; + } + // + // Read variable into the allocated buffer. + // + Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer); + if (EFI_ERROR (Status)) { + BufferSize = 0; + FreePool (Buffer); + Buffer = NULL; + } + } else { + // + // Variable not found or other errors met. + // + BufferSize = 0; + 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: + CopyMem ( + &Node.Guid, + &gEfiPcAnsiGuid, + sizeof (EFI_GUID) + ); + break; + + case VT100Type: + CopyMem ( + &Node.Guid, + &gEfiVT100Guid, + sizeof (EFI_GUID) + ); + break; + + case VT100PlusType: + CopyMem ( + &Node.Guid, + &gEfiVT100PlusGuid, + sizeof (EFI_GUID) + ); + break; + + case VTUTF8Type: + CopyMem ( + &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 = AppendDevicePathNode ( + 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; +} diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h new file mode 100644 index 0000000000..7ec24b3091 --- /dev/null +++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h @@ -0,0 +1,554 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + terminal.h + +Abstract: + + +Revision History + +--*/ + +#ifndef _TERMINAL_H +#define _TERMINAL_H + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#define RAW_FIFO_MAX_NUMBER 256 +#define FIFO_MAX_NUMBER 128 + +typedef struct { + UINT8 Head; + UINT8 Tail; + UINT8 Data[RAW_FIFO_MAX_NUMBER + 1]; +} RAW_DATA_FIFO; + +typedef struct { + UINT8 Head; + UINT8 Tail; + UINT16 Data[FIFO_MAX_NUMBER + 1]; +} UNICODE_FIFO; + +typedef struct { + UINT8 Head; + UINT8 Tail; + EFI_INPUT_KEY Data[FIFO_MAX_NUMBER + 1]; +} EFI_KEY_FIFO; + +#define TERMINAL_DEV_SIGNATURE EFI_SIGNATURE_32 ('t', 'm', 'n', 'l') + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + UINT8 TerminalType; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + VENDOR_DEVICE_PATH Node; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleInput; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SimpleTextOutput; + EFI_SIMPLE_TEXT_OUTPUT_MODE SimpleTextOutputMode; + UINTN SerialInTimeOut; + RAW_DATA_FIFO RawFiFo; + UNICODE_FIFO UnicodeFiFo; + EFI_KEY_FIFO EfiKeyFiFo; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + EFI_EVENT TwoSecondTimeOut; + UINT32 InputState; + UINT32 ResetState; + + // + // Esc could not be output to the screen by user, + // but the terminal driver need to output it to + // the terminal emulation software to send control sequence. + // This boolean is used by the terminal driver only + // to indicate whether the Esc could be sent or not. + // + BOOLEAN OutputEscChar; +} TERMINAL_DEV; + +#define INPUT_STATE_DEFAULT 0x00 +#define INPUT_STATE_ESC 0x01 +#define INPUT_STATE_CSI 0x02 +#define INPUT_STATE_LEFTOPENBRACKET 0x04 +#define INPUT_STATE_O 0x08 +#define INPUT_STATE_2 0x10 + +#define RESET_STATE_DEFAULT 0x00 +#define RESET_STATE_ESC_R 0x01 +#define RESET_STATE_ESC_R_ESC_r 0x02 + +#define TERMINAL_CON_IN_DEV_FROM_THIS(a) CR (a, TERMINAL_DEV, SimpleInput, TERMINAL_DEV_SIGNATURE) +#define TERMINAL_CON_OUT_DEV_FROM_THIS(a) CR (a, TERMINAL_DEV, SimpleTextOutput, TERMINAL_DEV_SIGNATURE) + +typedef union { + UINT8 Utf8_1; + UINT8 Utf8_2[2]; + UINT8 Utf8_3[3]; +} UTF8_CHAR; + +#define PcAnsiType 0 +#define VT100Type 1 +#define VT100PlusType 2 +#define VTUTF8Type 3 + +#define LEFTOPENBRACKET 0x5b // '[' +#define ACAP 0x41 +#define BCAP 0x42 +#define CCAP 0x43 +#define DCAP 0x44 + +#define MODE0_COLUMN_COUNT 80 +#define MODE0_ROW_COUNT 25 + +#define BACKSPACE 8 +#define ESC 27 +#define CSI 0x9B +#define DEL 127 +#define BRIGHT_CONTROL_OFFSET 2 +#define FOREGROUND_CONTROL_OFFSET 6 +#define BACKGROUND_CONTROL_OFFSET 11 +#define ROW_OFFSET 2 +#define COLUMN_OFFSET 5 + +typedef struct { + UINT16 Unicode; + CHAR8 PcAnsi; + CHAR8 Ascii; +} UNICODE_TO_CHAR; + +#define VarConsoleInpDev L"ConInDev" +#define VarConsoleOutDev L"ConOutDev" +#define VarErrorOutDev L"ErrOutDev" + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gTerminalComponentName; + +// +// Prototypes +// +EFI_STATUS +EFIAPI +InitializeTerminal ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +EFI_STATUS +EFIAPI +TerminalConInReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +EFI_STATUS +EFIAPI +TerminalConInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +; + +VOID +EFIAPI +TerminalConInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +; + +EFI_STATUS +EFIAPI +TerminalDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +TerminalDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +TerminalDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +EFI_STATUS +EFIAPI +TerminalComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +TerminalComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// internal functions +// +EFI_STATUS +TerminalConInCheckForKey ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This + ) +; + +VOID +TerminalUpdateConsoleDevVariable ( + IN CHAR16 *VariableName, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath + ) +; + +VOID +TerminalRemoveConsoleDevVariable ( + IN CHAR16 *VariableName, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath + ) +; + +VOID * +TerminalGetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VariableSize + ) +; + +EFI_STATUS +SetTerminalDevicePath ( + IN UINT8 TerminalType, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + OUT EFI_DEVICE_PATH_PROTOCOL **TerminalDevicePath + ) +; + +VOID +InitializeRawFiFo ( + IN TERMINAL_DEV *TerminalDevice + ) +; + +VOID +InitializeUnicodeFiFo ( + IN TERMINAL_DEV *TerminalDevice + ) +; + +VOID +InitializeEfiKeyFiFo ( + IN TERMINAL_DEV *TerminalDevice + ) +; + +EFI_STATUS +GetOneKeyFromSerial ( + EFI_SERIAL_IO_PROTOCOL *SerialIo, + UINT8 *Input + ) +; + +BOOLEAN +RawFiFoInsertOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT8 Input + ) +; + +BOOLEAN +RawFiFoRemoveOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT8 *Output + ) +; + +BOOLEAN +IsRawFiFoEmpty ( + TERMINAL_DEV *TerminalDevice + ) +; + +BOOLEAN +IsRawFiFoFull ( + TERMINAL_DEV *TerminalDevice + ) +; + +BOOLEAN +EfiKeyFiFoInsertOneKey ( + TERMINAL_DEV *TerminalDevice, + EFI_INPUT_KEY Key + ) +; + +BOOLEAN +EfiKeyFiFoRemoveOneKey ( + TERMINAL_DEV *TerminalDevice, + EFI_INPUT_KEY *Output + ) +; + +BOOLEAN +IsEfiKeyFiFoEmpty ( + TERMINAL_DEV *TerminalDevice + ) +; + +BOOLEAN +IsEfiKeyFiFoFull ( + TERMINAL_DEV *TerminalDevice + ) +; + +BOOLEAN +UnicodeFiFoInsertOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT16 Input + ) +; + +BOOLEAN +UnicodeFiFoRemoveOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT16 *Output + ) +; + +BOOLEAN +IsUnicodeFiFoEmpty ( + TERMINAL_DEV *TerminalDevice + ) +; + +BOOLEAN +IsUnicodeFiFoFull ( + TERMINAL_DEV *TerminalDevice + ) +; + +UINT8 +UnicodeFiFoGetKeyCount ( + TERMINAL_DEV *TerminalDevice + ) +; + +VOID +TranslateRawDataToEfiKey ( + IN TERMINAL_DEV *TerminalDevice + ) +; + +// +// internal functions for PC ANSI +// +VOID +AnsiRawDataToUnicode ( + IN TERMINAL_DEV *PcAnsiDevice + ) +; + +VOID +UnicodeToEfiKey ( + IN TERMINAL_DEV *PcAnsiDevice + ) +; + +EFI_STATUS +AnsiTestString ( + IN TERMINAL_DEV *TerminalDevice, + IN CHAR16 *WString + ) +; + +// +// internal functions for VT100 +// +EFI_STATUS +VT100TestString ( + IN TERMINAL_DEV *VT100Device, + IN CHAR16 *WString + ) +; + +// +// internal functions for VT100Plus +// +EFI_STATUS +VT100PlusTestString ( + IN TERMINAL_DEV *TerminalDevice, + IN CHAR16 *WString + ) +; + +// +// internal functions for VTUTF8 +// +VOID +VTUTF8RawDataToUnicode ( + IN TERMINAL_DEV *VtUtf8Device + ) +; + +EFI_STATUS +VTUTF8TestString ( + IN TERMINAL_DEV *TerminalDevice, + IN CHAR16 *WString + ) +; + +VOID +UnicodeToUtf8 ( + IN CHAR16 Unicode, + OUT UTF8_CHAR *Utf8Char, + OUT UINT8 *ValidBytes + ) +; + +VOID +GetOneValidUtf8Char ( + IN TERMINAL_DEV *Utf8Device, + OUT UTF8_CHAR *Utf8Char, + OUT UINT8 *ValidBytes + ) +; + +VOID +Utf8ToUnicode ( + IN UTF8_CHAR Utf8Char, + IN UINT8 ValidBytes, + OUT CHAR16 *UnicodeChar + ) +; + +// +// functions for boxdraw unicode +// +BOOLEAN +TerminalIsValidTextGraphics ( + IN CHAR16 Graphic, + OUT CHAR8 *PcAnsi, OPTIONAL + OUT CHAR8 *Ascii OPTIONAL + ) +; + +BOOLEAN +TerminalIsValidAscii ( + IN CHAR16 Ascii + ) +; + +BOOLEAN +TerminalIsValidEfiCntlChar ( + IN CHAR16 CharC + ) +; + +#endif diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.inf b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.inf new file mode 100644 index 0000000000..358db95606 --- /dev/null +++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.inf @@ -0,0 +1,117 @@ +#/** @file +# Component description file for Terminal module. +# +# This driver installs Simple Text In/Out protocol for terminal devices (serial devices or hotplug devices). +# Copyright (c) 2006 - 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Terminal + FILE_GUID = 9E863906-A40F-4875-977F-5B93FF237FC6 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + ENTRY_POINT = InitializeTerminal + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gTerminalDriverBinding +# COMPONENT_NAME = gTerminalComponentName +# + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ + +[Sources.common] + ComponentName.c + vtutf8.c + ansi.c + TerminalConOut.c + TerminalConIn.c + Terminal.c + Terminal.h + CommonHeader.h + EntryPoint.c + + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + +################################################################################ +# +# Library Class Section - list of Library Classes that are required for +# this module. +# +################################################################################ + +[LibraryClasses] + DevicePathLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + ReportStatusCodeLib + UefiLib + UefiDriverEntryPoint + DebugLib + + +################################################################################ +# +# Guid C Name Section - list of Guids that this module uses or produces. +# +################################################################################ + +[Guids] + gEfiGlobalVariableGuid # SOMETIMES_CONSUMED L"ErrOutDev" + gEfiVTUTF8Guid # SOMETIMES_CONSUMED + gEfiVT100Guid # SOMETIMES_CONSUMED + gEfiVT100PlusGuid # SOMETIMES_CONSUMED + gEfiPcAnsiGuid # SOMETIMES_CONSUMED + + +################################################################################ +# +# Protocol C Name Section - list of Protocol and Protocol Notify C Names +# that this module uses or produces. +# +################################################################################ + +[Protocols] + gEfiHotPlugDeviceGuid # PROTOCOL SOMETIMES_CONSUMED + gEfiSerialIoProtocolGuid # PROTOCOL TO_START + gEfiDevicePathProtocolGuid # PROTOCOL TO_START + gEfiSimpleTextInProtocolGuid # PROTOCOL BY_START + gEfiSimpleTextOutProtocolGuid # PROTOCOL BY_START + diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.msa b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.msa new file mode 100644 index 0000000000..1c1dc0680d --- /dev/null +++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.msa @@ -0,0 +1,129 @@ + + + + Terminal + DXE_DRIVER + 9E863906-A40F-4875-977F-5B93FF237FC6 + 1.0 + Component description file for Terminal module. + This driver installs Simple Text In/Out protocol for terminal devices (serial devices or hotplug devices). + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + Terminal + + + + DebugLib + Recommended libary Instance is PeiDxeDebugLibReportStatusCode instance in MdePkg. + + + UefiDriverModelLib + + + UefiDriverEntryPoint + + + UefiLib + + + ReportStatusCodeLib + + + BaseMemoryLib + + + MemoryAllocationLib + + + UefiBootServicesTableLib + + + UefiRuntimeServicesTableLib + + + DevicePathLib + + + + Terminal.h + Terminal.c + TerminalConIn.c + TerminalConOut.c + ansi.c + vtutf8.c + ComponentName.c + + + + + + + + gEfiSimpleTextOutProtocolGuid + + + gEfiSimpleTextInProtocolGuid + + + gEfiDevicePathProtocolGuid + + + gEfiSerialIoProtocolGuid + + + gEfiHotPlugDeviceGuid + + + + + 0x0043 0x006F 0x006E 0x0049 0x006E 0x0044 0x0065 0x0076 + gEfiGlobalVariableGuid + L"ConInDev" global variable will be updated if the serial device is not a hot plug device. + + + 0x0043 0x006F 0x006E 0x004F 0x0075 0x0074 0x0044 0x0065 0x0076 + gEfiGlobalVariableGuid + L"ConOutDev" global variable will be updated if the serial device is not a hot plug device. + + + 0x0045 0x0072 0x0072 0x004F 0x0075 0x0074 0x0044 0x0065 0x0076 + gEfiGlobalVariableGuid + L"ErrOutDev" global variable will be updated if the serial device is not a hot plug device. + + + + + gEfiGlobalVariableGuid + + + gEfiPcAnsiGuid + + + gEfiVT100PlusGuid + + + gEfiVT100Guid + + + gEfiVTUTF8Guid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + gTerminalDriverBinding + gTerminalComponentName + + + \ No newline at end of file diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c new file mode 100644 index 0000000000..952024b712 --- /dev/null +++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c @@ -0,0 +1,1184 @@ +/**@file + Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol. + +Copyright (c) 2006 - 2007 Intel Corporation.
+All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "Terminal.h" + +#include "FrameworkDxe.h" + +EFI_STATUS +EFIAPI +TerminalConInReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset(). + This driver only perform dependent serial device reset regardless of + the value of ExtendeVerification + + Arguments: + + This - Indicates the calling context. + + ExtendedVerification - Skip by this driver. + + Returns: + + EFI_SUCCESS + The reset operation succeeds. + + EFI_DEVICE_ERROR + The dependent serial port reset fails. + +--*/ +{ + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This); + + // + // Report progress code here + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET, + TerminalDevice->DevicePath + ); + + Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo); + + // + // clear all the internal buffer for keys + // + InitializeRawFiFo (TerminalDevice); + InitializeUnicodeFiFo (TerminalDevice); + InitializeEfiKeyFiFo (TerminalDevice); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, + TerminalDevice->DevicePath + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +TerminalConInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke(). + + Arguments: + + This - Indicates the calling context. + + Key - A pointer to a buffer that is filled in with the keystroke + information for the key that was sent from terminal. + + Returns: + + EFI_SUCCESS + The keystroke information is returned successfully. + + EFI_NOT_READY + There is no keystroke data available. + + EFI_DEVICE_ERROR + The dependent serial device encounters error. + +--*/ +{ + TERMINAL_DEV *TerminalDevice; + EFI_STATUS Status; + + // + // Initialize *Key to nonsense value. + // + Key->ScanCode = SCAN_NULL; + Key->UnicodeChar = 0; + // + // get TERMINAL_DEV from "This" parameter. + // + TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This); + + Status = TerminalConInCheckForKey (This); + if (EFI_ERROR (Status)) { + return EFI_NOT_READY; + } + + EfiKeyFiFoRemoveOneKey (TerminalDevice, Key); + + return EFI_SUCCESS; + +} + +VOID +TranslateRawDataToEfiKey ( + IN TERMINAL_DEV *TerminalDevice + ) +/*++ + Step1: Turn raw data into Unicode (according to different encode). + Step2: Translate Unicode into key information. + (according to different terminal standard). +--*/ +{ + switch (TerminalDevice->TerminalType) { + + case PcAnsiType: + case VT100Type: + case VT100PlusType: + AnsiRawDataToUnicode (TerminalDevice); + UnicodeToEfiKey (TerminalDevice); + break; + + case VTUTF8Type: + // + // Process all the raw data in the RawFIFO, + // put the processed key into UnicodeFIFO. + // + VTUTF8RawDataToUnicode (TerminalDevice); + + // + // Translate all the Unicode data in the UnicodeFIFO to Efi key, + // then put into EfiKeyFIFO. + // + UnicodeToEfiKey (TerminalDevice); + + break; + } +} + +VOID +EFIAPI +TerminalConInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + Routine Description: + + Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event + Signal the event if there is key available + + Arguments: + + Event - Indicates the event that invoke this function. + + Context - Indicates the calling context. + + Returns: + + N/A + +--*/ +{ + // + // Someone is waiting on the keystroke event, if there's + // a key pending, signal the event + // + // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL + // + if (!EFI_ERROR (TerminalConInCheckForKey (Context))) { + + gBS->SignalEvent (Event); + } +} + +EFI_STATUS +TerminalConInCheckForKey ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This + ) +/*++ + Routine Description: + + Check for a pending key in the Efi Key FIFO or Serial device buffer. + + Arguments: + + This - Indicates the calling context. + + Returns: + + EFI_SUCCESS + There is key pending. + + EFI_NOT_READY + There is no key pending. + + EFI_DEVICE_ERROR + +--*/ +{ + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + UINT32 Control; + UINT8 Input; + EFI_SERIAL_IO_MODE *Mode; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + UINTN SerialInTimeOut; + + TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This); + + SerialIo = TerminalDevice->SerialIo; + if (SerialIo == NULL) { + return EFI_DEVICE_ERROR; + } + // + // 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) { + 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) { + // + // Translate all the raw data in RawFIFO into EFI Key, + // according to different terminal type supported. + // + TranslateRawDataToEfiKey (TerminalDevice); + + // + // if there is pre-fetched Efi Key in EfiKeyFIFO buffer, + // return directly. + // + if (!IsEfiKeyFiFoEmpty (TerminalDevice)) { + return EFI_SUCCESS; + } else { + return EFI_NOT_READY; + } + } + // + // Fetch all the keys in the serial buffer, + // and insert the byte stream into RawFIFO. + // + do { + + 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); + } while (TRUE); + + // + // Translate all the raw data in RawFIFO into EFI Key, + // according to different terminal type supported. + // + TranslateRawDataToEfiKey (TerminalDevice); + + if (IsEfiKeyFiFoEmpty (TerminalDevice)) { + return EFI_NOT_READY; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetOneKeyFromSerial ( + EFI_SERIAL_IO_PROTOCOL *SerialIo, + UINT8 *Input + ) +/*++ + Get one key out of serial buffer. + If serial buffer is empty, return EFI_NOT_READY; + if reading serial buffer encounter error, returns EFI_DEVICE_ERROR; + if reading serial buffer successfully, put the fetched key to + the parameter "Input", and return EFI_SUCCESS. +--*/ +{ + EFI_STATUS Status; + UINTN Size; + + Size = 1; + *Input = 0; + + Status = SerialIo->Read (SerialIo, &Size, Input); + + if (EFI_ERROR (Status)) { + + if (Status == EFI_TIMEOUT) { + return EFI_NOT_READY; + } + + return EFI_DEVICE_ERROR; + + } + + if (*Input == 0) { + return EFI_NOT_READY; + } + + return EFI_SUCCESS; +} + +BOOLEAN +RawFiFoInsertOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT8 Input + ) +/*++ + Insert one byte raw data into the Raw Data FIFO. + If FIFO is FULL before data insertion, + return FALSE, and the key is lost. +--*/ +{ + UINT8 Tail; + + Tail = TerminalDevice->RawFiFo.Tail; + + if (IsRawFiFoFull (TerminalDevice)) { + // + // Raw FIFO is full + // + return FALSE; + } + + TerminalDevice->RawFiFo.Data[Tail] = Input; + + TerminalDevice->RawFiFo.Tail = (UINT8) ((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)); + + return TRUE; +} + +BOOLEAN +RawFiFoRemoveOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT8 *Output + ) +/*++ + Remove one byte raw data out of the Raw Data FIFO. + If FIFO buffer is empty before remove operation, + return FALSE. +--*/ +{ + UINT8 Head; + + Head = TerminalDevice->RawFiFo.Head; + + if (IsRawFiFoEmpty (TerminalDevice)) { + // + // FIFO is empty + // + *Output = 0; + return FALSE; + } + + *Output = TerminalDevice->RawFiFo.Data[Head]; + + TerminalDevice->RawFiFo.Head = (UINT8) ((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1)); + + return TRUE; +} + +BOOLEAN +IsRawFiFoEmpty ( + TERMINAL_DEV *TerminalDevice + ) +/*++ + Clarify whether FIFO buffer is empty. +--*/ +{ + if (TerminalDevice->RawFiFo.Head == TerminalDevice->RawFiFo.Tail) { + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +IsRawFiFoFull ( + TERMINAL_DEV *TerminalDevice + ) +/*++ + Clarify whether FIFO buffer is full. +--*/ +{ + UINT8 Tail; + UINT8 Head; + + Tail = TerminalDevice->RawFiFo.Tail; + Head = TerminalDevice->RawFiFo.Head; + + if (((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)) == Head) { + + return TRUE; + } + + return FALSE; +} + +BOOLEAN +EfiKeyFiFoInsertOneKey ( + TERMINAL_DEV *TerminalDevice, + EFI_INPUT_KEY Key + ) +/*++ + Insert one pre-fetched key into the FIFO buffer. + If FIFO buffer is FULL before key insertion, + return FALSE, and the key is lost. +--*/ +{ + UINT8 Tail; + + Tail = TerminalDevice->EfiKeyFiFo.Tail; + + if (IsEfiKeyFiFoFull (TerminalDevice)) { + // + // Efi Key FIFO is full + // + return FALSE; + } + + TerminalDevice->EfiKeyFiFo.Data[Tail] = Key; + + TerminalDevice->EfiKeyFiFo.Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1)); + + return TRUE; +} + +BOOLEAN +EfiKeyFiFoRemoveOneKey ( + TERMINAL_DEV *TerminalDevice, + EFI_INPUT_KEY *Output + ) +/*++ + Remove one pre-fetched key out of the FIFO buffer. + If FIFO buffer is empty before remove operation, + return FALSE. +--*/ +{ + UINT8 Head; + + Head = TerminalDevice->EfiKeyFiFo.Head; + + if (IsEfiKeyFiFoEmpty (TerminalDevice)) { + // + // FIFO is empty + // + Output->ScanCode = SCAN_NULL; + Output->UnicodeChar = 0; + return FALSE; + } + + *Output = TerminalDevice->EfiKeyFiFo.Data[Head]; + + TerminalDevice->EfiKeyFiFo.Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1)); + + return TRUE; +} + +BOOLEAN +IsEfiKeyFiFoEmpty ( + TERMINAL_DEV *TerminalDevice + ) +/*++ + Clarify whether FIFO buffer is empty. +--*/ +{ + if (TerminalDevice->EfiKeyFiFo.Head == TerminalDevice->EfiKeyFiFo.Tail) { + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +IsEfiKeyFiFoFull ( + TERMINAL_DEV *TerminalDevice + ) +/*++ + Clarify whether FIFO buffer is full. +--*/ +{ + UINT8 Tail; + UINT8 Head; + + Tail = TerminalDevice->EfiKeyFiFo.Tail; + Head = TerminalDevice->EfiKeyFiFo.Head; + + if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) { + + return TRUE; + } + + return FALSE; +} + +BOOLEAN +UnicodeFiFoInsertOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT16 Input + ) +/*++ + Insert one pre-fetched key into the FIFO buffer. + If FIFO buffer is FULL before key insertion, + return FALSE, and the key is lost. +--*/ +{ + UINT8 Tail; + + Tail = TerminalDevice->UnicodeFiFo.Tail; + + if (IsUnicodeFiFoFull (TerminalDevice)) { + // + // Unicode FIFO is full + // + return FALSE; + } + + TerminalDevice->UnicodeFiFo.Data[Tail] = Input; + + TerminalDevice->UnicodeFiFo.Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1)); + + return TRUE; +} + +BOOLEAN +UnicodeFiFoRemoveOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT16 *Output + ) +/*++ + Remove one pre-fetched key out of the FIFO buffer. + If FIFO buffer is empty before remove operation, + return FALSE. +--*/ +{ + UINT8 Head; + + Head = TerminalDevice->UnicodeFiFo.Head; + + if (IsUnicodeFiFoEmpty (TerminalDevice)) { + // + // FIFO is empty + // + Output = NULL; + return FALSE; + } + + *Output = TerminalDevice->UnicodeFiFo.Data[Head]; + + TerminalDevice->UnicodeFiFo.Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1)); + + return TRUE; +} + +BOOLEAN +IsUnicodeFiFoEmpty ( + TERMINAL_DEV *TerminalDevice + ) +/*++ + Clarify whether FIFO buffer is empty. +--*/ +{ + if (TerminalDevice->UnicodeFiFo.Head == TerminalDevice->UnicodeFiFo.Tail) { + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +IsUnicodeFiFoFull ( + TERMINAL_DEV *TerminalDevice + ) +/*++ + Clarify whether FIFO buffer is full. +--*/ +{ + UINT8 Tail; + UINT8 Head; + + Tail = TerminalDevice->UnicodeFiFo.Tail; + Head = TerminalDevice->UnicodeFiFo.Head; + + if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) { + + return TRUE; + } + + return FALSE; +} + +UINT8 +UnicodeFiFoGetKeyCount ( + TERMINAL_DEV *TerminalDevice + ) +{ + UINT8 Tail; + UINT8 Head; + + Tail = TerminalDevice->UnicodeFiFo.Tail; + Head = TerminalDevice->UnicodeFiFo.Head; + + if (Tail >= Head) { + return (UINT8) (Tail - Head); + } else { + return (UINT8) (Tail + FIFO_MAX_NUMBER + 1 - Head); + } +} + +STATIC +VOID +UnicodeToEfiKeyFlushState ( + IN TERMINAL_DEV *TerminalDevice + ) +{ + EFI_INPUT_KEY Key; + + if (TerminalDevice->InputState & INPUT_STATE_ESC) { + Key.ScanCode = SCAN_ESC; + Key.UnicodeChar = 0; + EfiKeyFiFoInsertOneKey (TerminalDevice, Key); + } + + if (TerminalDevice->InputState & INPUT_STATE_CSI) { + Key.ScanCode = SCAN_NULL; + Key.UnicodeChar = CSI; + EfiKeyFiFoInsertOneKey (TerminalDevice, Key); + } + + if (TerminalDevice->InputState & INPUT_STATE_LEFTOPENBRACKET) { + Key.ScanCode = SCAN_NULL; + Key.UnicodeChar = LEFTOPENBRACKET; + EfiKeyFiFoInsertOneKey (TerminalDevice, Key); + } + + if (TerminalDevice->InputState & INPUT_STATE_O) { + Key.ScanCode = SCAN_NULL; + Key.UnicodeChar = 'O'; + EfiKeyFiFoInsertOneKey (TerminalDevice, Key); + } + + if (TerminalDevice->InputState & INPUT_STATE_2) { + Key.ScanCode = SCAN_NULL; + Key.UnicodeChar = '2'; + EfiKeyFiFoInsertOneKey (TerminalDevice, Key); + } + + gBS->SetTimer ( + TerminalDevice->TwoSecondTimeOut, + TimerCancel, + 0 + ); + + TerminalDevice->InputState = INPUT_STATE_DEFAULT; +} + +VOID +UnicodeToEfiKey ( + IN TERMINAL_DEV *TerminalDevice + ) +/*++ + Routine Description: + + Converts a stream of Unicode characters from a terminal input device into EFI Keys that + can be read through the Simple Input Protocol. The table below shows the keyboard + input mappings that this function supports. If the ESC sequence listed in one of the + columns is presented, then it is translated into the coorespoding EFI Scan Code. If a + matching sequence is not found, then the raw key strokes are converted into EFI Keys. + + 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not + completed in 2 seconds, then the raw key strokes of the partial ESC sequence are + converted into EFI Keys. + + There is one special input sequence that will force the system to reset. + This is ESC R ESC r ESC R. + + Arguments: + + TerminaDevice : The terminal device to use to translate raw input into EFI Keys + + Returns: + + None + +Symbols used in table below +=========================== + ESC = 0x1B + CSI = 0x9B + DEL = 0x7f + ^ = CTRL + ++=========+======+===========+==========+==========+ +| | EFI | EFI 1.10 | | | +| | Scan | | VT100+ | | +| KEY | Code | PC ANSI | VTUTF8 | VT100 | ++=========+======+===========+==========+==========+ +| NULL | 0x00 | | | | +| UP | 0x01 | ESC [ A | ESC [ A | ESC [ A | +| DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B | +| RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C | +| LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D | +| HOME | 0x05 | ESC [ H | ESC h | ESC [ H | +| END | 0x06 | ESC [ F | ESC k | ESC [ K | +| INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ | +| | | ESC [ L | | ESC [ L | +| DELETE | 0x08 | ESC [ X | ESC - | ESC [ P | +| PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V | +| | | | | ESC [ ? | +| PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U | +| | | | | ESC [ / | +| F1 | 0x0B | ESC [ M | ESC 1 | ESC O P | +| F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q | +| F3 | 0x0D | ESC [ O | ESC 3 | ESC O w | +| F4 | 0x0E | ESC [ P | ESC 4 | ESC O x | +| F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t | +| F6 | 0x10 | ESC [ R | ESC 6 | ESC O u | +| F7 | 0x11 | ESC [ S | ESC 7 | ESC O q | +| F8 | 0x12 | ESC [ T | ESC 8 | ESC O r | +| F9 | 0x13 | ESC [ U | ESC 9 | ESC O p | +| F10 | 0x14 | ESC [ V | ESC 0 | ESC O M | +| Escape | 0x17 | ESC | ESC | ESC | ++=========+======+===========+==========+=========+ + +Special Mappings +================ +ESC R ESC r ESC R = Reset System + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS TimerStatus; + UINT16 UnicodeChar; + EFI_INPUT_KEY Key; + BOOLEAN SetDefaultResetState; + + TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut); + + if (!EFI_ERROR (TimerStatus)) { + UnicodeToEfiKeyFlushState (TerminalDevice); + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + } + + while (!IsUnicodeFiFoEmpty(TerminalDevice)) { + + if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) { + // + // Check to see if the 2 second timer has expired + // + TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut); + if (!EFI_ERROR (TimerStatus)) { + UnicodeToEfiKeyFlushState (TerminalDevice); + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + } + } + + // + // Fetch one Unicode character from the Unicode FIFO + // + UnicodeFiFoRemoveOneKey (TerminalDevice,&UnicodeChar); + + SetDefaultResetState = TRUE; + + switch (TerminalDevice->InputState) { + case INPUT_STATE_DEFAULT: + + break; + + case INPUT_STATE_ESC: + + if (UnicodeChar == LEFTOPENBRACKET) { + TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET; + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + continue; + } + + if (UnicodeChar == 'O' && TerminalDevice->TerminalType == VT100Type) { + TerminalDevice->InputState |= INPUT_STATE_O; + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + continue; + } + + Key.ScanCode = SCAN_NULL; + + if (TerminalDevice->TerminalType == VT100PlusType || + TerminalDevice->TerminalType == VTUTF8Type) { + switch (UnicodeChar) { + case '1': + Key.ScanCode = SCAN_F1; + break; + case '2': + Key.ScanCode = SCAN_F2; + break; + case '3': + Key.ScanCode = SCAN_F3; + break; + case '4': + Key.ScanCode = SCAN_F4; + break; + case '5': + Key.ScanCode = SCAN_F5; + break; + case '6': + Key.ScanCode = SCAN_F6; + break; + case '7': + Key.ScanCode = SCAN_F7; + break; + case '8': + Key.ScanCode = SCAN_F8; + break; + case '9': + Key.ScanCode = SCAN_F9; + break; + case '0': + Key.ScanCode = SCAN_F10; + break; + case 'h': + Key.ScanCode = SCAN_HOME; + break; + case 'k': + Key.ScanCode = SCAN_END; + break; + case '+': + Key.ScanCode = SCAN_INSERT; + break; + case '-': + Key.ScanCode = SCAN_DELETE; + break; + case '/': + Key.ScanCode = SCAN_PAGE_DOWN; + break; + case '?': + Key.ScanCode = SCAN_PAGE_UP; + break; + default : + break; + } + } + + switch (UnicodeChar) { + case 'R': + if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) { + TerminalDevice->ResetState = RESET_STATE_ESC_R; + SetDefaultResetState = FALSE; + } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_r) { + gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); + } + Key.ScanCode = SCAN_NULL; + break; + case 'r': + if (TerminalDevice->ResetState == RESET_STATE_ESC_R) { + TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_r; + SetDefaultResetState = FALSE; + } + Key.ScanCode = SCAN_NULL; + break; + default : + break; + } + + if (SetDefaultResetState) { + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + } + + if (Key.ScanCode != SCAN_NULL) { + Key.UnicodeChar = 0; + EfiKeyFiFoInsertOneKey (TerminalDevice,Key); + TerminalDevice->InputState = INPUT_STATE_DEFAULT; + UnicodeToEfiKeyFlushState (TerminalDevice); + continue; + } + + UnicodeToEfiKeyFlushState (TerminalDevice); + + break; + + case INPUT_STATE_ESC | INPUT_STATE_O: + + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + + Key.ScanCode = SCAN_NULL; + + if (TerminalDevice->TerminalType == VT100Type) { + switch (UnicodeChar) { + case 'P': + Key.ScanCode = SCAN_F1; + break; + case 'Q': + Key.ScanCode = SCAN_F2; + break; + case 'w': + Key.ScanCode = SCAN_F3; + break; + case 'x': + Key.ScanCode = SCAN_F4; + break; + case 't': + Key.ScanCode = SCAN_F5; + break; + case 'u': + Key.ScanCode = SCAN_F6; + break; + case 'q': + Key.ScanCode = SCAN_F7; + break; + case 'r': + Key.ScanCode = SCAN_F8; + break; + case 'p': + Key.ScanCode = SCAN_F9; + break; + case 'M': + Key.ScanCode = SCAN_F10; + break; + default : + break; + } + } + + if (Key.ScanCode != SCAN_NULL) { + Key.UnicodeChar = 0; + EfiKeyFiFoInsertOneKey (TerminalDevice,Key); + TerminalDevice->InputState = INPUT_STATE_DEFAULT; + UnicodeToEfiKeyFlushState (TerminalDevice); + continue; + } + + UnicodeToEfiKeyFlushState (TerminalDevice); + + break; + + case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET: + + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + + Key.ScanCode = SCAN_NULL; + + if (TerminalDevice->TerminalType == PcAnsiType || + TerminalDevice->TerminalType == VT100Type || + TerminalDevice->TerminalType == VT100PlusType || + TerminalDevice->TerminalType == VTUTF8Type) { + switch (UnicodeChar) { + case 'A': + Key.ScanCode = SCAN_UP; + break; + case 'B': + Key.ScanCode = SCAN_DOWN; + break; + case 'C': + Key.ScanCode = SCAN_RIGHT; + break; + case 'D': + Key.ScanCode = SCAN_LEFT; + break; + case 'H': + if (TerminalDevice->TerminalType == PcAnsiType || + TerminalDevice->TerminalType == VT100Type) { + Key.ScanCode = SCAN_HOME; + } + break; + case 'F': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_END; + } + break; + case 'K': + if (TerminalDevice->TerminalType == VT100Type) { + Key.ScanCode = SCAN_END; + } + break; + case 'L': + case '@': + if (TerminalDevice->TerminalType == PcAnsiType || + TerminalDevice->TerminalType == VT100Type) { + Key.ScanCode = SCAN_INSERT; + } + break; + case 'X': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_DELETE; + } + break; + case 'P': + if (TerminalDevice->TerminalType == VT100Type) { + Key.ScanCode = SCAN_DELETE; + } else if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F4; + } + break; + case 'I': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_PAGE_UP; + } + break; + case 'V': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F10; + } + case '?': + if (TerminalDevice->TerminalType == VT100Type) { + Key.ScanCode = SCAN_PAGE_UP; + } + break; + case 'G': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_PAGE_DOWN; + } + break; + case 'U': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F9; + } + case '/': + if (TerminalDevice->TerminalType == VT100Type) { + Key.ScanCode = SCAN_PAGE_DOWN; + } + break; + case 'M': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F1; + } + break; + case 'N': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F2; + } + break; + case 'O': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F3; + } + break; + case 'Q': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F5; + } + break; + case 'R': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F6; + } + break; + case 'S': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F7; + } + break; + case 'T': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F8; + } + break; + default : + break; + } + } + + if (Key.ScanCode != SCAN_NULL) { + Key.UnicodeChar = 0; + EfiKeyFiFoInsertOneKey (TerminalDevice,Key); + TerminalDevice->InputState = INPUT_STATE_DEFAULT; + UnicodeToEfiKeyFlushState (TerminalDevice); + continue; + } + + UnicodeToEfiKeyFlushState (TerminalDevice); + + break; + + + default: + // + // Invalid state. This should never happen. + // + ASSERT (FALSE); + + UnicodeToEfiKeyFlushState (TerminalDevice); + + break; + } + + if (UnicodeChar == ESC) { + TerminalDevice->InputState = INPUT_STATE_ESC; + } + + if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) { + Status = gBS->SetTimer( + TerminalDevice->TwoSecondTimeOut, + TimerRelative, + (UINT64)20000000 + ); + ASSERT_EFI_ERROR (Status); + continue; + } + + if (SetDefaultResetState) { + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + } + + if (UnicodeChar == DEL) { + Key.ScanCode = SCAN_DELETE; + Key.UnicodeChar = 0; + } else { + Key.ScanCode = SCAN_NULL; + Key.UnicodeChar = UnicodeChar; + } + + EfiKeyFiFoInsertOneKey (TerminalDevice,Key); + } +} diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c new file mode 100644 index 0000000000..b5a9f33e14 --- /dev/null +++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c @@ -0,0 +1,1002 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + TerminalConOut.c + +Abstract: + + +Revision History +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "Terminal.h" + +#include "FrameworkDxe.h" + +// +// This list is used to define the valid extend chars. +// It also provides a mapping from Unicode to PCANSI or +// ASCII. The ASCII mapping we just made up. +// +// +STATIC UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = { + { BOXDRAW_HORIZONTAL, 0xc4, L'-' }, + { BOXDRAW_VERTICAL, 0xb3, L'|' }, + { BOXDRAW_DOWN_RIGHT, 0xda, L'/' }, + { BOXDRAW_DOWN_LEFT, 0xbf, L'\\' }, + { BOXDRAW_UP_RIGHT, 0xc0, L'\\' }, + { BOXDRAW_UP_LEFT, 0xd9, L'/' }, + { BOXDRAW_VERTICAL_RIGHT, 0xc3, L'|' }, + { BOXDRAW_VERTICAL_LEFT, 0xb4, L'|' }, + { BOXDRAW_DOWN_HORIZONTAL, 0xc2, L'+' }, + { BOXDRAW_UP_HORIZONTAL, 0xc1, L'+' }, + { BOXDRAW_VERTICAL_HORIZONTAL, 0xc5, L'+' }, + { BOXDRAW_DOUBLE_HORIZONTAL, 0xcd, L'-' }, + { BOXDRAW_DOUBLE_VERTICAL, 0xba, L'|' }, + { BOXDRAW_DOWN_RIGHT_DOUBLE, 0xd5, L'/' }, + { BOXDRAW_DOWN_DOUBLE_RIGHT, 0xd6, L'/' }, + { BOXDRAW_DOUBLE_DOWN_RIGHT, 0xc9, L'/' }, + { BOXDRAW_DOWN_LEFT_DOUBLE, 0xb8, L'\\' }, + { BOXDRAW_DOWN_DOUBLE_LEFT, 0xb7, L'\\' }, + { BOXDRAW_DOUBLE_DOWN_LEFT, 0xbb, L'\\' }, + { BOXDRAW_UP_RIGHT_DOUBLE, 0xd4, L'\\' }, + { BOXDRAW_UP_DOUBLE_RIGHT, 0xd3, L'\\' }, + { BOXDRAW_DOUBLE_UP_RIGHT, 0xc8, L'\\' }, + { BOXDRAW_UP_LEFT_DOUBLE, 0xbe, L'/' }, + { BOXDRAW_UP_DOUBLE_LEFT, 0xbd, L'/' }, + { BOXDRAW_DOUBLE_UP_LEFT, 0xbc, L'/' }, + { BOXDRAW_VERTICAL_RIGHT_DOUBLE, 0xc6, L'|' }, + { BOXDRAW_VERTICAL_DOUBLE_RIGHT, 0xc7, L'|' }, + { BOXDRAW_DOUBLE_VERTICAL_RIGHT, 0xcc, L'|' }, + { BOXDRAW_VERTICAL_LEFT_DOUBLE, 0xb5, L'|' }, + { BOXDRAW_VERTICAL_DOUBLE_LEFT, 0xb6, L'|' }, + { BOXDRAW_DOUBLE_VERTICAL_LEFT, 0xb9, L'|' }, + { BOXDRAW_DOWN_HORIZONTAL_DOUBLE, 0xd1, L'+' }, + { BOXDRAW_DOWN_DOUBLE_HORIZONTAL, 0xd2, L'+' }, + { BOXDRAW_DOUBLE_DOWN_HORIZONTAL, 0xcb, L'+' }, + { BOXDRAW_UP_HORIZONTAL_DOUBLE, 0xcf, L'+' }, + { BOXDRAW_UP_DOUBLE_HORIZONTAL, 0xd0, L'+' }, + { BOXDRAW_DOUBLE_UP_HORIZONTAL, 0xca, L'+' }, + { BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE, 0xd8, L'+' }, + { BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL, 0xd7, L'+' }, + { BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL, 0xce, L'+' }, + + { BLOCKELEMENT_FULL_BLOCK, 0xdb, L'*' }, + { BLOCKELEMENT_LIGHT_SHADE, 0xb0, L'+' }, + + { GEOMETRICSHAPE_UP_TRIANGLE, 0x1e, L'^' }, + { GEOMETRICSHAPE_RIGHT_TRIANGLE, 0x10, L'>' }, + { GEOMETRICSHAPE_DOWN_TRIANGLE, 0x1f, L'v' }, + { GEOMETRICSHAPE_LEFT_TRIANGLE, 0x11, L'<' }, + + { ARROW_LEFT, 0x3c, L'<' }, + { ARROW_UP, 0x18, L'^' }, + { ARROW_RIGHT, 0x3e, L'>' }, + { ARROW_DOWN, 0x19, L'v' }, + + { 0x0000, 0x00, L'\0' } +}; + +CHAR16 mSetModeString[] = { ESC, '[', '=', '3', 'h', 0 }; +CHAR16 mSetAttributeString[] = { ESC, '[', '0', 'm', ESC, '[', '4', '0', 'm', ESC, '[', '4', '0', 'm', 0 }; +CHAR16 mClearScreenString[] = { ESC, '[', '2', 'J', 0 }; +CHAR16 mSetCursorPositionString[] = { ESC, '[', '0', '0', ';', '0', '0', 'H', 0 }; + +// +// Body of the ConOut functions +// +EFI_STATUS +EFIAPI +TerminalConOutReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset(). + If ExtendeVerification is TRUE, then perform dependent serial device reset, + and set display mode to mode 0. + If ExtendedVerification is FALSE, only set display mode to mode 0. + + Arguments: + + This - Indicates the calling context. + + ExtendedVerification - Indicates that the driver may perform a more exhaustive + verification operation of the device during reset. + + Returns: + + EFI_SUCCESS + The reset operation succeeds. + + EFI_DEVICE_ERROR + The terminal is not functioning correctly or the serial port reset fails. + +--*/ +{ + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // Perform a more exhaustive reset by resetting the serial port. + // + if (ExtendedVerification) { + // + // Report progress code here + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET, + TerminalDevice->DevicePath + ); + + Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo); + if (EFI_ERROR (Status)) { + // + // Report error code here + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, + TerminalDevice->DevicePath + ); + + return Status; + } + } + + This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)); + + Status = This->SetMode (This, 0); + + return Status; +} + +EFI_STATUS +EFIAPI +TerminalConOutOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString(). + The Unicode string will be converted to terminal expressible data stream + and send to terminal via serial port. + + + Arguments: + + This - Indicates the calling context. + + WString - The Null-terminated Unicode string to be displayed on + the terminal screen. + + Returns: + + EFI_SUCCESS + The string is output successfully. + + EFI_DEVICE_ERROR + The serial port fails to send the string out. + + EFI_WARN_UNKNOWN_GLYPH + Indicates that some of the characters in the Unicode string could not + be rendered and are skipped. + + EFI_UNSUPPORTED + +--*/ +{ + TERMINAL_DEV *TerminalDevice; + EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; + UINTN MaxColumn; + UINTN MaxRow; + UINTN Length; + UTF8_CHAR Utf8Char; + CHAR8 GraphicChar; + CHAR8 AsciiChar; + EFI_STATUS Status; + UINT8 ValidBytes; + // + // flag used to indicate whether condition happens which will cause + // return EFI_WARN_UNKNOWN_GLYPH + // + BOOLEAN Warning; + + ValidBytes = 0; + Warning = FALSE; + + // + // get Terminal device data structure pointer. + // + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // get current display mode + // Terminal driver only support mode 0 + // + Mode = This->Mode; + if (Mode->Mode != 0) { + return EFI_UNSUPPORTED; + } + + This->QueryMode ( + This, + Mode->Mode, + &MaxColumn, + &MaxRow + ); + + for (; *WString != CHAR_NULL; WString++) { + + switch (TerminalDevice->TerminalType) { + + case PcAnsiType: + case VT100Type: + case VT100PlusType: + + if (!TerminalIsValidTextGraphics (*WString, &GraphicChar, &AsciiChar)) { + // + // If it's not a graphic character convert Unicode to ASCII. + // + GraphicChar = (CHAR8) *WString; + + if (!(TerminalIsValidAscii (GraphicChar) || TerminalIsValidEfiCntlChar (GraphicChar))) { + // + // when this driver use the OutputString to output control string, + // TerminalDevice->OutputEscChar is set to let the Esc char + // to be output to the terminal emulation software. + // + if ((GraphicChar == 27) && TerminalDevice->OutputEscChar) { + GraphicChar = 27; + } else { + GraphicChar = '?'; + Warning = TRUE; + } + } + + AsciiChar = GraphicChar; + + } + + if (TerminalDevice->TerminalType != PcAnsiType) { + GraphicChar = AsciiChar; + } + + Length = 1; + + Status = TerminalDevice->SerialIo->Write ( + TerminalDevice->SerialIo, + &Length, + &GraphicChar + ); + + if (EFI_ERROR (Status)) { + goto OutputError; + } + + break; + + case VTUTF8Type: + UnicodeToUtf8 (*WString, &Utf8Char, &ValidBytes); + Length = ValidBytes; + Status = TerminalDevice->SerialIo->Write ( + TerminalDevice->SerialIo, + &Length, + (UINT8 *) &Utf8Char + ); + if (EFI_ERROR (Status)) { + goto OutputError; + } + break; + } + // + // Update cursor position. + // + switch (*WString) { + + case CHAR_BACKSPACE: + if (Mode->CursorColumn > 0) { + Mode->CursorColumn--; + } + break; + + case CHAR_LINEFEED: + if (Mode->CursorRow < (INT32) (MaxRow - 1)) { + Mode->CursorRow++; + } + break; + + case CHAR_CARRIAGE_RETURN: + Mode->CursorColumn = 0; + break; + + default: + if (Mode->CursorColumn < (INT32) (MaxColumn - 1)) { + + Mode->CursorColumn++; + + } else { + + Mode->CursorColumn = 0; + if (Mode->CursorRow < (INT32) (MaxRow - 1)) { + Mode->CursorRow++; + } + + } + break; + + }; + + } + + if (Warning) { + return EFI_WARN_UNKNOWN_GLYPH; + } + + return EFI_SUCCESS; + +OutputError: + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_OUTPUT_ERROR, + TerminalDevice->DevicePath + ); + + return EFI_DEVICE_ERROR; +} + +EFI_STATUS +EFIAPI +TerminalConOutTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString(). + If one of the characters in the *Wstring is + neither valid Unicode drawing characters, + not ASCII code, then this function will return + EFI_UNSUPPORTED. + + + Arguments: + + This - Indicates the calling context. + + WString - The Null-terminated Unicode string to be tested. + + Returns: + + EFI_SUCCESS + The terminal is capable of rendering the output string. + + EFI_UNSUPPORTED + Some of the characters in the Unicode string cannot be rendered. + +--*/ +{ + TERMINAL_DEV *TerminalDevice; + EFI_STATUS Status; + + // + // get Terminal device data structure pointer. + // + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + switch (TerminalDevice->TerminalType) { + + case PcAnsiType: + case VT100Type: + case VT100PlusType: + Status = AnsiTestString (TerminalDevice, WString); + break; + + case VTUTF8Type: + Status = VTUTF8TestString (TerminalDevice, WString); + break; + + default: + Status = EFI_UNSUPPORTED; + break; + } + + return Status; +} + +EFI_STATUS +EFIAPI +TerminalConOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode(). + It returns information for an available text mode + that the terminal supports. + In this driver, we only support text mode 80x25, which is + defined as mode 0. + + + Arguments: + + *This + Indicates the calling context. + + ModeNumber + The mode number to return information on. + + Columns + The returned columns of the requested mode. + + Rows + The returned rows of the requested mode. + + Returns: + + EFI_SUCCESS + The requested mode information is returned. + + EFI_UNSUPPORTED + The mode number is not valid. + + EFI_DEVICE_ERROR + +--*/ +{ + if (This->Mode->MaxMode > 1) { + return EFI_DEVICE_ERROR; + } + + if (ModeNumber == 0) { + + *Columns = MODE0_COLUMN_COUNT; + *Rows = MODE0_ROW_COUNT; + + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +TerminalConOutSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUT.SetMode(). + Set the terminal to a specified display mode. + In this driver, we only support mode 0. + + Arguments: + + This + Indicates the calling context. + + ModeNumber + The text mode to set. + + Returns: + + EFI_SUCCESS + The requested text mode is set. + + EFI_DEVICE_ERROR + The requested text mode cannot be set because of serial device error. + + EFI_UNSUPPORTED + The text mode number is not valid. + +--*/ +{ + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + // + // get Terminal device data structure pointer. + // + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + if (ModeNumber != 0) { + return EFI_UNSUPPORTED; + } + + This->Mode->Mode = 0; + + This->ClearScreen (This); + + TerminalDevice->OutputEscChar = TRUE; + Status = This->OutputString (This, mSetModeString); + TerminalDevice->OutputEscChar = FALSE; + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + This->Mode->Mode = 0; + + Status = This->ClearScreen (This); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; + +} + +EFI_STATUS +EFIAPI +TerminalConOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute(). + + Arguments: + + This + Indicates the calling context. + + Attribute + The attribute to set. Only bit0..6 are valid, all other bits + are undefined and must be zero. + + Returns: + + EFI_SUCCESS + The requested attribute is set. + + EFI_DEVICE_ERROR + The requested attribute cannot be set due to serial port error. + + EFI_UNSUPPORTED + The attribute requested is not defined by EFI spec. + +--*/ +{ + UINT8 ForegroundControl; + UINT8 BackgroundControl; + UINT8 BrightControl; + INT32 SavedColumn; + INT32 SavedRow; + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + SavedColumn = 0; + SavedRow = 0; + + // + // get Terminal device data structure pointer. + // + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // only the bit0..6 of the Attribute is valid + // + if ((Attribute | 0x7f) != 0x7f) { + return EFI_UNSUPPORTED; + } + // + // convert Attribute value to terminal emulator + // understandable foreground color + // + switch (Attribute & 0x07) { + + case EFI_BLACK: + ForegroundControl = 30; + break; + + case EFI_BLUE: + ForegroundControl = 34; + break; + + case EFI_GREEN: + ForegroundControl = 32; + break; + + case EFI_CYAN: + ForegroundControl = 36; + break; + + case EFI_RED: + ForegroundControl = 31; + break; + + case EFI_MAGENTA: + ForegroundControl = 35; + break; + + case EFI_BROWN: + ForegroundControl = 33; + break; + + default: + + case EFI_LIGHTGRAY: + ForegroundControl = 37; + break; + + } + // + // bit4 of the Attribute indicates bright control + // of terminal emulator. + // + BrightControl = (UINT8) ((Attribute >> 3) & 1); + + // + // convert Attribute value to terminal emulator + // understandable background color. + // + switch ((Attribute >> 4) & 0x07) { + + case EFI_BLACK: + BackgroundControl = 40; + break; + + case EFI_BLUE: + BackgroundControl = 44; + break; + + case EFI_GREEN: + BackgroundControl = 42; + break; + + case EFI_CYAN: + BackgroundControl = 46; + break; + + case EFI_RED: + BackgroundControl = 41; + break; + + case EFI_MAGENTA: + BackgroundControl = 45; + break; + + case EFI_BROWN: + BackgroundControl = 43; + break; + + default: + + case EFI_LIGHTGRAY: + BackgroundControl = 47; + break; + } + // + // terminal emulator's control sequence to set attributes + // + mSetAttributeString[BRIGHT_CONTROL_OFFSET] = (CHAR16) ('0' + BrightControl); + mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 0] = (CHAR16) ('0' + (ForegroundControl / 10)); + mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 1] = (CHAR16) ('0' + (ForegroundControl % 10)); + mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 0] = (CHAR16) ('0' + (BackgroundControl / 10)); + mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 1] = (CHAR16) ('0' + (BackgroundControl % 10)); + + // + // save current column and row + // for future scrolling back use. + // + SavedColumn = This->Mode->CursorColumn; + SavedRow = This->Mode->CursorRow; + + TerminalDevice->OutputEscChar = TRUE; + Status = This->OutputString (This, mSetAttributeString); + TerminalDevice->OutputEscChar = FALSE; + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // scroll back to saved cursor position. + // + This->Mode->CursorColumn = SavedColumn; + This->Mode->CursorRow = SavedRow; + + This->Mode->Attribute = (INT32) Attribute; + + return EFI_SUCCESS; + +} + +EFI_STATUS +EFIAPI +TerminalConOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen(). + It clears the ANSI terminal's display to the + currently selected background color. + + + Arguments: + + This + Indicates the calling context. + + Returns: + + EFI_SUCCESS + The operation completed successfully. + + EFI_DEVICE_ERROR + The terminal screen cannot be cleared due to serial port error. + + EFI_UNSUPPORTED + The terminal is not in a valid display mode. + +--*/ +{ + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // control sequence for clear screen request + // + TerminalDevice->OutputEscChar = TRUE; + Status = This->OutputString (This, mClearScreenString); + TerminalDevice->OutputEscChar = FALSE; + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = This->SetCursorPosition (This, 0, 0); + + return Status; +} + +EFI_STATUS +EFIAPI +TerminalConOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition(). + + Arguments: + + This + Indicates the calling context. + + Column + The row to set cursor to. + + Row + The column to set cursor to. + + Returns: + + EFI_SUCCESS + The operation completed successfully. + + EFI_DEVICE_ERROR + The request fails due to serial port error. + + EFI_UNSUPPORTED + The terminal is not in a valid text mode, or the cursor position + is invalid for current mode. + +--*/ +{ + EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; + UINTN MaxColumn; + UINTN MaxRow; + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // get current mode + // + Mode = This->Mode; + + // + // get geometry of current mode + // + Status = This->QueryMode ( + This, + Mode->Mode, + &MaxColumn, + &MaxRow + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + if (Column >= MaxColumn || Row >= MaxRow) { + return EFI_UNSUPPORTED; + } + // + // control sequence to move the cursor + // + mSetCursorPositionString[ROW_OFFSET + 0] = (CHAR16) ('0' + ((Row + 1) / 10)); + mSetCursorPositionString[ROW_OFFSET + 1] = (CHAR16) ('0' + ((Row + 1) % 10)); + mSetCursorPositionString[COLUMN_OFFSET + 0] = (CHAR16) ('0' + ((Column + 1) / 10)); + mSetCursorPositionString[COLUMN_OFFSET + 1] = (CHAR16) ('0' + ((Column + 1) % 10)); + + TerminalDevice->OutputEscChar = TRUE; + Status = This->OutputString (This, mSetCursorPositionString); + TerminalDevice->OutputEscChar = FALSE; + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // update current cursor position + // in the Mode data structure. + // + Mode->CursorColumn = (INT32) Column; + Mode->CursorRow = (INT32) Row; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +TerminalConOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.EnableCursor(). + In this driver, the cursor cannot be hidden. + + Arguments: + + This + Indicates the calling context. + + Visible + If TRUE, the cursor is set to be visible, + If FALSE, the cursor is set to be invisible. + + Returns: + + EFI_SUCCESS + The request is valid. + + EFI_UNSUPPORTED + The terminal does not support cursor hidden. + +--*/ +{ + if (!Visible) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +BOOLEAN +TerminalIsValidTextGraphics ( + IN CHAR16 Graphic, + OUT CHAR8 *PcAnsi, OPTIONAL + OUT CHAR8 *Ascii OPTIONAL + ) +/*++ + +Routine Description: + + Detects if a Unicode char is for Box Drawing text graphics. + +Arguments: + + Graphic - Unicode char to test. + + PcAnsi - Optional pointer to return PCANSI equivalent of Graphic. + + Ascii - Optional pointer to return ASCII equivalent of Graphic. + +Returns: + + TRUE if Graphic is a supported Unicode Box Drawing character. + +--*/ +{ + UNICODE_TO_CHAR *Table; + + if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) { + // + // Unicode drawing code charts are all in the 0x25xx range, + // arrows are 0x21xx + // + return FALSE; + } + + for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) { + if (Graphic == Table->Unicode) { + if (PcAnsi != NULL) { + *PcAnsi = Table->PcAnsi; + } + + if (Ascii != NULL) { + *Ascii = Table->Ascii; + } + + return TRUE; + } + } + + return FALSE; +} + +BOOLEAN +TerminalIsValidAscii ( + IN CHAR16 Ascii + ) +{ + // + // valid ascii code lies in the extent of 0x20 ~ 0x7f + // + if ((Ascii >= 0x20) && (Ascii <= 0x7f)) { + return TRUE; + } + + return FALSE; +} + +BOOLEAN +TerminalIsValidEfiCntlChar ( + IN CHAR16 CharC + ) +{ + // + // only support four control characters. + // + if (CharC == CHAR_NULL || + CharC == CHAR_BACKSPACE || + CharC == CHAR_LINEFEED || + CharC == CHAR_CARRIAGE_RETURN || + CharC == CHAR_TAB + ) { + return TRUE; + } + + return FALSE; +} diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/ansi.c b/MdeModulePkg/Universal/Console/TerminalDxe/ansi.c new file mode 100644 index 0000000000..c3ebe245bf --- /dev/null +++ b/MdeModulePkg/Universal/Console/TerminalDxe/ansi.c @@ -0,0 +1,73 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ansi.c + +Abstract: + + +Revision History +--*/ + + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "Terminal.h" + +VOID +AnsiRawDataToUnicode ( + IN TERMINAL_DEV *TerminalDevice + ) +{ + UINT8 RawData; + + // + // pop the raw data out from the raw fifo, + // and translate it into unicode, then push + // the unicode into unicode fifo, until the raw fifo is empty. + // + while (!IsRawFiFoEmpty (TerminalDevice)) { + + RawFiFoRemoveOneKey (TerminalDevice, &RawData); + + UnicodeFiFoInsertOneKey (TerminalDevice, (UINT16) RawData); + } +} + +EFI_STATUS +AnsiTestString ( + IN TERMINAL_DEV *TerminalDevice, + IN CHAR16 *WString + ) +{ + CHAR8 GraphicChar; + + // + // support three kind of character: + // valid ascii, valid efi control char, valid text graphics. + // + for (; *WString != CHAR_NULL; WString++) { + + if ( !(TerminalIsValidAscii (*WString) || + TerminalIsValidEfiCntlChar (*WString) || + TerminalIsValidTextGraphics (*WString, &GraphicChar, NULL) )) { + + return EFI_UNSUPPORTED; + } + } + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/vtutf8.c b/MdeModulePkg/Universal/Console/TerminalDxe/vtutf8.c new file mode 100644 index 0000000000..72e0920c8a --- /dev/null +++ b/MdeModulePkg/Universal/Console/TerminalDxe/vtutf8.c @@ -0,0 +1,275 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + vtutf8.c + +Abstract: + + +Revision History +--*/ + + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "Terminal.h" + +VOID +VTUTF8RawDataToUnicode ( + IN TERMINAL_DEV *TerminalDevice + ) +{ + UTF8_CHAR Utf8Char; + UINT8 ValidBytes; + UINT16 UnicodeChar; + + ValidBytes = 0; + // + // pop the raw data out from the raw fifo, + // and translate it into unicode, then push + // the unicode into unicode fifo, until the raw fifo is empty. + // + while (!IsRawFiFoEmpty (TerminalDevice)) { + + GetOneValidUtf8Char (TerminalDevice, &Utf8Char, &ValidBytes); + + if (ValidBytes < 1 || ValidBytes > 3) { + continue; + } + + Utf8ToUnicode (Utf8Char, ValidBytes, (CHAR16 *) &UnicodeChar); + + UnicodeFiFoInsertOneKey (TerminalDevice, UnicodeChar); + } +} + +VOID +GetOneValidUtf8Char ( + IN TERMINAL_DEV *Utf8Device, + OUT UTF8_CHAR *Utf8Char, + OUT UINT8 *ValidBytes + ) +{ + UINT8 Temp; + UINT8 Index; + BOOLEAN FetchFlag; + + Temp = 0; + Index = 0; + FetchFlag = TRUE; + + // + // if no valid Utf8 char is found in the RawFiFo, + // then *ValidBytes will be zero. + // + *ValidBytes = 0; + + while (!IsRawFiFoEmpty (Utf8Device)) { + + RawFiFoRemoveOneKey (Utf8Device, &Temp); + + switch (*ValidBytes) { + + case 0: + if ((Temp & 0x80) == 0) { + // + // one-byte utf8 char + // + *ValidBytes = 1; + + Utf8Char->Utf8_1 = Temp; + + FetchFlag = FALSE; + + } else if ((Temp & 0xe0) == 0xc0) { + // + // two-byte utf8 char + // + *ValidBytes = 2; + + Utf8Char->Utf8_2[1] = Temp; + + } else if ((Temp & 0xf0) == 0xe0) { + // + // three-byte utf8 char + // + *ValidBytes = 3; + + Utf8Char->Utf8_3[2] = Temp; + + Index++; + + } else { + // + // reset *ValidBytes to zero, let valid utf8 char search restart + // + *ValidBytes = 0; + } + + break; + + case 2: + if ((Temp & 0xc0) == 0x80) { + + Utf8Char->Utf8_2[0] = Temp; + + FetchFlag = FALSE; + + } else { + + *ValidBytes = 0; + } + break; + + case 3: + if ((Temp & 0xc0) == 0x80) { + + Utf8Char->Utf8_3[2 - Index] = Temp; + Index++; + if (Index == 3) { + FetchFlag = FALSE; + } + } else { + + *ValidBytes = 0; + Index = 0; + } + break; + + default: + break; + } + + if (!FetchFlag) { + break; + } + } + + return ; +} + +VOID +Utf8ToUnicode ( + IN UTF8_CHAR Utf8Char, + IN UINT8 ValidBytes, + OUT CHAR16 *UnicodeChar + ) +{ + UINT8 UnicodeByte0; + UINT8 UnicodeByte1; + UINT8 Byte0; + UINT8 Byte1; + UINT8 Byte2; + + *UnicodeChar = 0; + + // + // translate utf8 code to unicode, in terminal standard, + // up to 3 bytes utf8 code is supported. + // + switch (ValidBytes) { + case 1: + // + // one-byte utf8 code + // + *UnicodeChar = (UINT16) Utf8Char.Utf8_1; + break; + + case 2: + // + // two-byte utf8 code + // + Byte0 = Utf8Char.Utf8_2[0]; + Byte1 = Utf8Char.Utf8_2[1]; + + UnicodeByte0 = (UINT8) ((Byte1 << 6) | (Byte0 & 0x3f)); + UnicodeByte1 = (UINT8) ((Byte1 >> 2) & 0x07); + *UnicodeChar = (UINT16) (UnicodeByte0 | (UnicodeByte1 << 8)); + break; + + case 3: + // + // three-byte utf8 code + // + Byte0 = Utf8Char.Utf8_3[0]; + Byte1 = Utf8Char.Utf8_3[1]; + Byte2 = Utf8Char.Utf8_3[2]; + + UnicodeByte0 = (UINT8) ((Byte1 << 6) | (Byte0 & 0x3f)); + UnicodeByte1 = (UINT8) ((Byte2 << 4) | ((Byte1 >> 2) & 0x0f)); + *UnicodeChar = (UINT16) (UnicodeByte0 | (UnicodeByte1 << 8)); + + default: + break; + } + + return ; +} + +VOID +UnicodeToUtf8 ( + IN CHAR16 Unicode, + OUT UTF8_CHAR *Utf8Char, + OUT UINT8 *ValidBytes + ) +{ + UINT8 UnicodeByte0; + UINT8 UnicodeByte1; + // + // translate unicode to utf8 code + // + UnicodeByte0 = (UINT8) Unicode; + UnicodeByte1 = (UINT8) (Unicode >> 8); + + if (Unicode < 0x0080) { + + Utf8Char->Utf8_1 = (UINT8) (UnicodeByte0 & 0x7f); + *ValidBytes = 1; + + } else if (Unicode < 0x0800) { + // + // byte sequence: high -> low + // Utf8_2[0], Utf8_2[1] + // + Utf8Char->Utf8_2[1] = (UINT8) ((UnicodeByte0 & 0x3f) + 0x80); + Utf8Char->Utf8_2[0] = (UINT8) ((((UnicodeByte1 << 2) + (UnicodeByte0 >> 6)) & 0x1f) + 0xc0); + + *ValidBytes = 2; + + } else { + // + // byte sequence: high -> low + // Utf8_3[0], Utf8_3[1], Utf8_3[2] + // + Utf8Char->Utf8_3[2] = (UINT8) ((UnicodeByte0 & 0x3f) + 0x80); + Utf8Char->Utf8_3[1] = (UINT8) ((((UnicodeByte1 << 2) + (UnicodeByte0 >> 6)) & 0x3f) + 0x80); + Utf8Char->Utf8_3[0] = (UINT8) (((UnicodeByte1 >> 4) & 0x0f) + 0xe0); + + *ValidBytes = 3; + } +} + +EFI_STATUS +VTUTF8TestString ( + IN TERMINAL_DEV *TerminalDevice, + IN CHAR16 *WString + ) +{ + // + // to utf8, all kind of characters are supported. + // + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Universal/DevicePathDxe/CommonHeader.h b/MdeModulePkg/Universal/DevicePathDxe/CommonHeader.h new file mode 100644 index 0000000000..24b9be38b4 --- /dev/null +++ b/MdeModulePkg/Universal/DevicePathDxe/CommonHeader.h @@ -0,0 +1,44 @@ +/**@file + Common header file shared by all source files. + + This file includes package header files, library classes and protocol, PPI & GUID definitions. + + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + + +// +// The package level header files this module uses +// +#include +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePath.c b/MdeModulePkg/Universal/DevicePathDxe/DevicePath.c new file mode 100644 index 0000000000..fc92fc986f --- /dev/null +++ b/MdeModulePkg/Universal/DevicePathDxe/DevicePath.c @@ -0,0 +1,114 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DevicePathDriver.c + +Abstract: + + Device Path Driver to produce DevPathUtilities Protocol, DevPathFromText Protocol + and DevPathToText Protocol. + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "DevicePath.h" + +EFI_HANDLE mDevicePathHandle = NULL; + +GLOBAL_REMOVE_IF_UNREFERENCED const EFI_DEVICE_PATH_UTILITIES_PROTOCOL mDevicePathUtilities = { + GetDevicePathSizeProtocolInterface, + DuplicateDevicePathProtocolInterface, + AppendDevicePathProtocolInterface, + AppendDeviceNodeProtocolInterface, + AppendDevicePathInstanceProtocolInterface, + GetNextDevicePathInstanceProtocolInterface, + IsDevicePathMultiInstanceProtocolInterface, + CreateDeviceNodeProtocolInterface +}; + +GLOBAL_REMOVE_IF_UNREFERENCED const EFI_DEVICE_PATH_TO_TEXT_PROTOCOL mDevicePathToText = { + ConvertDeviceNodeToText, + ConvertDevicePathToText +}; + +GLOBAL_REMOVE_IF_UNREFERENCED const EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL mDevicePathFromText = { + ConvertTextToDeviceNode, + ConvertTextToDevicePath +}; + +GLOBAL_REMOVE_IF_UNREFERENCED const EFI_GUID mEfiDevicePathMessagingUartFlowControlGuid = DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL; +GLOBAL_REMOVE_IF_UNREFERENCED const EFI_GUID mEfiDevicePathMessagingSASGuid = DEVICE_PATH_MESSAGING_SAS; + +EFI_STATUS +EFIAPI +DevicePathEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + + Routine Description: + Entry point for EFI drivers. + + Arguments: + ImageHandle - EFI_HANDLE + SystemTable - EFI_SYSTEM_TABLE + + Returns: + EFI_SUCCESS + others + +--*/ +{ + EFI_STATUS Status; + + Status = EFI_UNSUPPORTED; + if (FeaturePcdGet (PcdDevicePathSupportDevicePathToText)) { + if (FeaturePcdGet (PcdDevicePathSupportDevicePathFromText)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &mDevicePathHandle, + &gEfiDevicePathUtilitiesProtocolGuid, &mDevicePathUtilities, + &gEfiDevicePathToTextProtocolGuid, &mDevicePathToText, + &gEfiDevicePathFromTextProtocolGuid, &mDevicePathFromText, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &mDevicePathHandle, + &gEfiDevicePathUtilitiesProtocolGuid, &mDevicePathUtilities, + &gEfiDevicePathToTextProtocolGuid, &mDevicePathToText, + NULL + ); + } + } else { + if (FeaturePcdGet (PcdDevicePathSupportDevicePathFromText)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &mDevicePathHandle, + &gEfiDevicePathUtilitiesProtocolGuid, &mDevicePathUtilities, + &gEfiDevicePathFromTextProtocolGuid, &mDevicePathFromText, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &mDevicePathHandle, + &gEfiDevicePathUtilitiesProtocolGuid, &mDevicePathUtilities, + NULL + ); + } + } + return Status; +} diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePath.h b/MdeModulePkg/Universal/DevicePathDxe/DevicePath.h new file mode 100644 index 0000000000..9473b89e37 --- /dev/null +++ b/MdeModulePkg/Universal/DevicePathDxe/DevicePath.h @@ -0,0 +1,412 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DevicePath.h + +Abstract: + Definition for Device Path Utilities driver + +--*/ + +#ifndef _DEVICE_PATH_DRIVER_H +#define _DEVICE_PATH_DRIVER_H + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +extern const EFI_GUID mEfiDevicePathMessagingUartFlowControlGuid; +extern const EFI_GUID mEfiDevicePathMessagingSASGuid; + +#define MAX_CHAR 480 + +#define MIN_ALIGNMENT_SIZE sizeof(UINTN) +#define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0) + +#define IS_COMMA(a) ((a) == L',') +#define IS_HYPHEN(a) ((a) == L'-') +#define IS_DOT(a) ((a) == L'.') +#define IS_LEFT_PARENTH(a) ((a) == L'(') +#define IS_RIGHT_PARENTH(a) ((a) == L')') +#define IS_SLASH(a) ((a) == L'/') +#define IS_NULL(a) ((a) == L'\0') + +#define DEVICE_NODE_END 1 +#define DEVICE_PATH_INSTANCE_END 2 +#define DEVICE_PATH_END 3 + +#define SetDevicePathInstanceEndNode(a) { \ + (a)->Type = END_DEVICE_PATH_TYPE; \ + (a)->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; \ + (a)->Length[0] = sizeof (EFI_DEVICE_PATH_PROTOCOL); \ + (a)->Length[1] = 0; \ + } + +// +// Private Data structure +// +typedef struct { + CHAR16 *Str; + UINTN Len; + UINTN MaxLen; +} POOL_PRINT; + +typedef struct { + UINT8 Type; + UINT8 SubType; + VOID (*Function) (POOL_PRINT *, VOID *, BOOLEAN, BOOLEAN); +} DEVICE_PATH_TO_TEXT_TABLE; + +typedef struct { + CHAR16 *DevicePathNodeText; + EFI_DEVICE_PATH_PROTOCOL * (*Function) (CHAR16 *); +} DEVICE_PATH_FROM_TEXT_TABLE; + +typedef struct { + BOOLEAN ClassExist; + UINT8 Class; + BOOLEAN SubClassExist; + UINT8 SubClass; +} USB_CLASS_TEXT; + +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_CDCCONTROL 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_IMAGE 6 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_CDCDATA 10 +#define USB_CLASS_SMART_CARD 11 +#define USB_CLASS_VIDEO 14 +#define USB_CLASS_DIAGNOSTIC 220 +#define USB_CLASS_WIRELESS 224 + +#define USB_CLASS_RESERVE 254 +#define USB_SUBCLASS_FW_UPDATE 1 +#define USB_SUBCLASS_IRDA_BRIDGE 2 +#define USB_SUBCLASS_TEST 3 + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_HARDWARE_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_MESSAGING_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_MEDIA_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 HID; + UINT32 UID; + UINT32 CID; + CHAR8 HidUidCidStr[3]; +} ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 NetworkProtocol; + UINT16 LoginOption; + UINT16 Reserved; + UINT16 TargetPortalGroupTag; + UINT64 Lun; + CHAR16 iSCSITargetName[1]; +} ISCSI_DEVICE_PATH_WITH_NAME; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEVICE_PATH_WITH_DATA; + +CHAR16 * +ConvertDeviceNodeToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +/*++ + + Routine Description: + Convert a device node to its text representation. + + Arguments: + DeviceNode - Points to the device node to be converted. + DisplayOnly - If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + AllowShortcuts - If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + Returns: + A pointer - a pointer to the allocated text representation of the device node. + NULL - if DeviceNode is NULL or there was insufficient memory. + +--*/ +; + +CHAR16 * +ConvertDevicePathToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +/*++ + + Routine Description: + Convert a device path to its text representation. + + Arguments: + DeviceNode - Points to the device path to be converted. + DisplayOnly - If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + AllowShortcuts - If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + Returns: + A pointer - a pointer to the allocated text representation of the device path. + NULL - if DeviceNode is NULL or there was insufficient memory. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +ConvertTextToDeviceNode ( + IN CONST CHAR16 *TextDeviceNode + ) +/*++ + + Routine Description: + Convert text to the binary representation of a device node. + + Arguments: + TextDeviceNode - TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + Returns: + A pointer - Pointer to the EFI device node. + NULL - if TextDeviceNode is NULL or there was insufficient memory. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +ConvertTextToDevicePath ( + IN CONST CHAR16 *TextDevicePath + ) +/*++ + + Routine Description: + Convert text to the binary representation of a device path. + + Arguments: + TextDevicePath - TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device node character. + + Returns: + A pointer - Pointer to the allocated device path. + NULL - if TextDeviceNode is NULL or there was insufficient memory. + +--*/ +; + +UINTN +GetDevicePathSizeProtocolInterface ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + + Routine Description: + Returns the size of the device path, in bytes. + + Arguments: + DevicePath - Points to the start of the EFI device path. + + Returns: + Size - Size of the specified device path, in bytes, including the end-of-path tag. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +DuplicateDevicePathProtocolInterface ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + + Routine Description: + Create a duplicate of the specified path. + + Arguments: + DevicePath - Points to the source EFI device path. + + Returns: + Pointer - A pointer to the duplicate device path. + NULL - Insufficient memory. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePathProtocolInterface ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *Src1, + IN CONST EFI_DEVICE_PATH_PROTOCOL *Src2 + ) +/*++ + + Routine Description: + Create a new path by appending the second device path to the first. + + Arguments: + Src1 - Points to the first device path. If NULL, then it is ignored. + Src2 - Points to the second device path. If NULL, then it is ignored. + + Returns: + Pointer - A pointer to the newly created device path. + NULL - Memory could not be allocated + or either DevicePath or DeviceNode is NULL. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +AppendDeviceNodeProtocolInterface ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode + ) +/*++ + + Routine Description: + Creates a new path by appending the device node to the device path. + + Arguments: + DevicePath - Points to the device path. + DeviceNode - Points to the device node. + + Returns: + Pointer - A pointer to the allocated device node. + NULL - Memory could not be allocated + or either DevicePath or DeviceNode is NULL. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePathInstanceProtocolInterface ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance + ) +/*++ + + Routine Description: + Creates a new path by appending the specified device path instance to the specified device path. + + Arguments: + DevicePath - Points to the device path. If NULL, then ignored. + DevicePathInstance - Points to the device path instance. + + Returns: + Pointer - A pointer to the newly created device path + NULL - Memory could not be allocated or DevicePathInstance is NULL. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +GetNextDevicePathInstanceProtocolInterface ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathInstance, + OUT UINTN *DevicePathInstanceSize + ) +/*++ + + Routine Description: + Creates a copy of the current device path instance and returns a pointer to the next device path instance. + + Arguments: + DevicePathInstance - On input, this holds the pointer to the current device path + instance. On output, this holds the pointer to the next + device path instance or NULL if there are no more device + path instances in the device path. + DevicePathInstanceSize - On output, this holds the size of the device path instance, + in bytes or zero, if DevicePathInstance is zero. + + Returns: + Pointer - A pointer to the copy of the current device path instance. + NULL - DevicePathInstace was NULL on entry or there was insufficient memory. + +--*/ +; + +BOOLEAN +IsDevicePathMultiInstanceProtocolInterface ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + + Routine Description: + Returns whether a device path is multi-instance. + + Arguments: + DevicePath - Points to the device path. If NULL, then ignored. + + Returns: + TRUE - The device path has more than one instance + FALSE - The device path is empty or contains only a single instance. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +CreateDeviceNodeProtocolInterface ( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength + ) +/*++ + + Routine Description: + Creates a device node + + Arguments: + NodeType - NodeType is the device node type (EFI_DEVICE_PATH.Type) for + the new device node. + NodeSubType - NodeSubType is the device node sub-type + EFI_DEVICE_PATH.SubType) for the new device node. + NodeLength - NodeLength is the length of the device node + (EFI_DEVICE_PATH.Length) for the new device node. + + Returns: + Pointer - A pointer to the newly created device node. + NULL - NodeLength is less than + the size of the header or there was insufficient memory. + +--*/ +; + +#endif diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePath.inf b/MdeModulePkg/Universal/DevicePathDxe/DevicePath.inf new file mode 100644 index 0000000000..7f76d4f0e7 --- /dev/null +++ b/MdeModulePkg/Universal/DevicePathDxe/DevicePath.inf @@ -0,0 +1,122 @@ +#/** @file +# Component description file for Device Path Driver. +# +# This driver implement these three UEFI deveice path protocols ( +# DevicePathUtilities, DevicePahtToText and DevicePathFromText) and install them. +# Copyright (c) 2006 - 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DevicePath + FILE_GUID = 9B680FCE-AD6B-4F3A-B60B-F59899003443 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00090000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + ENTRY_POINT = DevicePathEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ + +[Sources.common] + DevicePathUtilities.c + DevicePathToText.c + DevicePathFromText.c + DevicePath.h + DevicePath.c + CommonHeader.h + + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + + +################################################################################ +# +# Library Class Section - list of Library Classes that are required for +# this module. +# +################################################################################ + +[LibraryClasses] + PcdLib + DevicePathLib + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + UefiDriverEntryPoint + PrintLib + DebugLib + + +################################################################################ +# +# Guid C Name Section - list of Guids that this module uses or produces. +# +################################################################################ + +[Guids] + gEfiVTUTF8Guid # ALWAYS_CONSUMED + gEfiVT100Guid # ALWAYS_CONSUMED + gEfiVT100PlusGuid # ALWAYS_CONSUMED + gEfiPcAnsiGuid # ALWAYS_CONSUMED + + +################################################################################ +# +# Protocol C Name Section - list of Protocol and Protocol Notify C Names +# that this module uses or produces. +# +################################################################################ + +[Protocols] + gEfiDevicePathToTextProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gEfiDevicePathFromTextProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gEfiDevicePathUtilitiesProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gEfiDebugPortProtocolGuid # PROTOCOL ALWAYS_CONSUMED + + +################################################################################ +# +# Pcd FEATURE_FLAG - list of PCDs that this module is coded for. +# +################################################################################ + +[PcdsFeatureFlag.common] + PcdDevicePathSupportDevicePathFromText|gEfiEdkModulePkgTokenSpaceGuid + PcdDevicePathSupportDevicePathToText|gEfiEdkModulePkgTokenSpaceGuid + diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePath.msa b/MdeModulePkg/Universal/DevicePathDxe/DevicePath.msa new file mode 100644 index 0000000000..bd082809e3 --- /dev/null +++ b/MdeModulePkg/Universal/DevicePathDxe/DevicePath.msa @@ -0,0 +1,117 @@ + + + + DevicePath + DXE_DRIVER + 9B680FCE-AD6B-4F3A-B60B-F59899003443 + 1.0 + Component description file for Device Path Driver. + This driver implement these three UEFI deveice path protocols ( + DevicePathUtilities, DevicePahtToText and DevicePathFromText) and install them. + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + DevicePath + + + + DebugLib + Recommended libary Instance is PeiDxeDebugLibReportStatusCode instance in MdePkg. + + + PrintLib + Recommended libary Instance is BasePrintLib instance in MdePkg. + + + UefiDriverEntryPoint + + + BaseLib + + + BaseMemoryLib + + + MemoryAllocationLib + + + UefiBootServicesTableLib + + + DevicePathLib + Recommended libary Instance is UefiDevicePathLib instance in MdePkg. + + + PcdLib + + + + DevicePath.c + DevicePath.h + DevicePathFromText.c + DevicePathToText.c + DevicePathUtilities.c + + + + + + + + gEfiDebugPortProtocolGuid + + + gEfiDevicePathUtilitiesProtocolGuid + + + gEfiDevicePathFromTextProtocolGuid + + + gEfiDevicePathToTextProtocolGuid + + + + + gEfiPcAnsiGuid + + + gEfiVT100PlusGuid + + + gEfiVT100Guid + + + gEfiVTUTF8Guid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00090000 + + DevicePathEntryPoint + + + + + PcdDevicePathSupportDevicePathToText + gEfiEdkModulePkgTokenSpaceGuid + FALSE + If TRUE, then the Device Path To Text Protocol should be produced by the platform + + + PcdDevicePathSupportDevicePathFromText + gEfiEdkModulePkgTokenSpaceGuid + FALSE + If TRUE, then the Device Path From Text Protocol should be produced by the platform + + + \ No newline at end of file diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c b/MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c new file mode 100644 index 0000000000..18bb291a94 --- /dev/null +++ b/MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c @@ -0,0 +1,2375 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DevicePathFromText.c + +Abstract: + + DevicePathFromText protocol as defined in the UEFI 2.0 specification. + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "DevicePath.h" + +STATIC +CHAR16 * +StrDuplicate ( + IN CONST CHAR16 *Src + ) +/*++ + + Routine Description: + Duplicate a string + + Arguments: + Src - Source string + + Returns: + Duplicated string + +--*/ +{ + UINTN Length; + CHAR16 *ReturnStr; + + Length = StrLen ((CHAR16 *) Src); + + ReturnStr = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), (VOID *) Src); + + return ReturnStr; +} + +STATIC +CHAR16 * +GetParamByNodeName ( + IN CHAR16 *Str, + IN CHAR16 *NodeName + ) +/*++ + + Routine Description: + Get parameter in a pair of parentheses follow the given node name. + For example, given the "Pci(0,1)" and NodeName "Pci", it returns "0,1". + + Arguments: + Str - Device Path Text + NodeName - Name of the node + + Returns: + Parameter text for the node + +--*/ +{ + CHAR16 *ParamStr; + CHAR16 *StrPointer; + UINTN NodeNameLength; + UINTN ParameterLength; + + // + // Check whether the node name matchs + // + NodeNameLength = StrLen (NodeName); + if (CompareMem (Str, NodeName, NodeNameLength * sizeof (CHAR16)) != 0) { + return NULL; + } + + ParamStr = Str + NodeNameLength; + if (!IS_LEFT_PARENTH (*ParamStr)) { + return NULL; + } + + // + // Skip the found '(' and find first occurrence of ')' + // + ParamStr++; + ParameterLength = 0; + StrPointer = ParamStr; + while (!IS_NULL (*StrPointer)) { + if (IS_RIGHT_PARENTH (*StrPointer)) { + break; + } + StrPointer++; + ParameterLength++; + } + if (IS_NULL (*StrPointer)) { + // + // ')' not found + // + return NULL; + } + + ParamStr = AllocateCopyPool ((ParameterLength + 1) * sizeof (CHAR16), ParamStr); + if (ParamStr == NULL) { + return NULL; + } + // + // Terminate the parameter string + // + ParamStr[ParameterLength] = L'\0'; + + return ParamStr; +} + +STATIC +CHAR16 * +SplitStr ( + IN OUT CHAR16 **List, + IN CHAR16 Separator + ) +/*++ + + Routine Description: + Get current sub-string from a string list, before return + the list header is moved to next sub-string. The sub-string is separated + by the specified character. For example, the separator is ',', the string + list is "2,0,3", it returns "2", the remain list move to "2,3" + + Arguments: + List - A string list separated by the specified separator + Separator - The separator character + + Returns: + pointer - The current sub-string + +--*/ +{ + CHAR16 *Str; + CHAR16 *ReturnStr; + + Str = *List; + ReturnStr = Str; + + if (IS_NULL (*Str)) { + return ReturnStr; + } + + // + // Find first occurrence of the separator + // + while (!IS_NULL (*Str)) { + if (*Str == Separator) { + break; + } + Str++; + } + + if (*Str == Separator) { + // + // Find a sub-string, terminate it + // + *Str = L'\0'; + Str++; + } + + // + // Move to next sub-string + // + *List = Str; + + return ReturnStr; +} + +STATIC +CHAR16 * +GetNextParamStr ( + IN OUT CHAR16 **List + ) +{ + // + // The separator is comma + // + return SplitStr (List, L','); +} + +STATIC +CHAR16 * +GetNextDeviceNodeStr ( + IN OUT CHAR16 **DevicePath, + OUT BOOLEAN *IsInstanceEnd + ) +/*++ + + Routine Description: + Get one device node from entire device path text. + + Arguments: + Str - The entire device path text string + IsInstanceEnd - This node is the end of a device path instance + + Returns: + a pointer - A device node text + NULL - No more device node available + +--*/ +{ + CHAR16 *Str; + CHAR16 *ReturnStr; + UINTN ParenthesesStack; + + Str = *DevicePath; + if (IS_NULL (*Str)) { + return NULL; + } + + // + // Skip the leading '/', '(', ')' and ',' + // + while (!IS_NULL (*Str)) { + if (!IS_SLASH (*Str) && + !IS_COMMA (*Str) && + !IS_LEFT_PARENTH (*Str) && + !IS_RIGHT_PARENTH (*Str)) { + break; + } + Str++; + } + + ReturnStr = Str; + + // + // Scan for the separator of this device node, '/' or ',' + // + ParenthesesStack = 0; + while (!IS_NULL (*Str)) { + if ((IS_COMMA (*Str) || IS_SLASH (*Str)) && (ParenthesesStack == 0)) { + break; + } + + if (IS_LEFT_PARENTH (*Str)) { + ParenthesesStack++; + } else if (IS_RIGHT_PARENTH (*Str)) { + ParenthesesStack--; + } + + Str++; + } + + if (ParenthesesStack != 0) { + // + // The '(' doesn't pair with ')', invalid device path text + // + return NULL; + } + + if (IS_COMMA (*Str)) { + *IsInstanceEnd = TRUE; + *Str = L'\0'; + Str++; + } else { + *IsInstanceEnd = FALSE; + if (!IS_NULL (*Str)) { + *Str = L'\0'; + Str++; + } + } + + *DevicePath = Str; + + return ReturnStr; +} + +STATIC +BOOLEAN +IsHexDigit ( + OUT UINT8 *Digit, + IN CHAR16 Char + ) +/*++ + + Routine Description: + Determines if a Unicode character is a hexadecimal digit. + The test is case insensitive. + + Arguments: + Digit - Pointer to byte that receives the value of the hex character. + Char - Unicode character to test. + + Returns: + TRUE - If the character is a hexadecimal digit. + FALSE - Otherwise. + +--*/ +{ + if ((Char >= L'0') && (Char <= L'9')) { + *Digit = (UINT8) (Char - L'0'); + return TRUE; + } + + if ((Char >= L'A') && (Char <= L'F')) { + *Digit = (UINT8) (Char - L'A' + 0x0A); + return TRUE; + } + + if ((Char >= L'a') && (Char <= L'f')) { + *Digit = (UINT8) (Char - L'a' + 0x0A); + return TRUE; + } + + return FALSE; +} + +STATIC +EFI_STATUS +HexStringToBuf ( + IN OUT UINT8 *Buf, + IN OUT UINTN *Len, + IN CHAR16 *Str, + OUT UINTN *ConvertedStrLen OPTIONAL + ) +/*++ + + Routine Description: + Converts Unicode string to binary buffer. + The conversion may be partial. + The first character in the string that is not hex digit stops the conversion. + At a minimum, any blob of data could be represented as a hex string. + + Arguments: + Buf - Pointer to buffer that receives the data. + Len - Length in bytes of the buffer to hold converted data. + If routine return with EFI_SUCCESS, containing length of converted data. + If routine return with EFI_BUFFER_TOO_SMALL, containg length of buffer desired. + Str - String to be converted from. + ConvertedStrLen - Length of the Hex String consumed. + + Returns: + EFI_SUCCESS: Routine Success. + EFI_BUFFER_TOO_SMALL: The buffer is too small to hold converted data. + EFI_ + +--*/ +{ + UINTN HexCnt; + UINTN Idx; + UINTN BufferLength; + UINT8 Digit; + UINT8 Byte; + + // + // Find out how many hex characters the string has. + // + for (Idx = 0, HexCnt = 0; IsHexDigit (&Digit, Str[Idx]); Idx++, HexCnt++); + + if (HexCnt == 0) { + *Len = 0; + return EFI_SUCCESS; + } + // + // Two Unicode characters make up 1 buffer byte. Round up. + // + BufferLength = (HexCnt + 1) / 2; + + // + // Test if buffer is passed enough. + // + if (BufferLength > (*Len)) { + *Len = BufferLength; + return EFI_BUFFER_TOO_SMALL; + } + + *Len = BufferLength; + + for (Idx = 0; Idx < HexCnt; Idx++) { + + IsHexDigit (&Digit, Str[HexCnt - 1 - Idx]); + + // + // For odd charaters, write the lower nibble for each buffer byte, + // and for even characters, the upper nibble. + // + if ((Idx & 1) == 0) { + Byte = Digit; + } else { + Byte = Buf[Idx / 2]; + Byte &= 0x0F; + Byte = (UINT8) (Byte | Digit << 4); + } + + Buf[Idx / 2] = Byte; + } + + if (ConvertedStrLen != NULL) { + *ConvertedStrLen = HexCnt; + } + + return EFI_SUCCESS; +} + +STATIC +CHAR16 * +TrimHexStr ( + IN CHAR16 *Str + ) +/*++ + + Routine Description: + Skip the leading white space and '0x' or '0X' of a hex string + + Arguments: + Str - The hex string + + Returns: + +--*/ +{ + // + // skip preceeding white space + // + while (*Str && *Str == ' ') { + Str += 1; + } + // + // skip preceeding zeros + // + while (*Str && *Str == '0') { + Str += 1; + } + // + // skip preceeding character 'x' or 'X' + // + if (*Str && (*Str == 'x' || *Str == 'X')) { + Str += 1; + } + + return Str; +} + +STATIC +UINTN +Xtoi ( + IN CHAR16 *Str + ) +/*++ + +Routine Description: + + Convert hex string to uint + +Arguments: + + Str - The string + +Returns: + +--*/ +{ + UINTN Rvalue; + UINTN Length; + + ASSERT (Str != NULL); + + // + // convert hex digits + // + Rvalue = 0; + Length = sizeof (UINTN); + HexStringToBuf ((UINT8 *) &Rvalue, &Length, TrimHexStr (Str), NULL); + + return Rvalue; +} + +STATIC +VOID +Xtoi64 ( + IN CHAR16 *Str, + IN UINT64 *Data + ) +/*++ + +Routine Description: + + Convert hex string to 64 bit data. + +Arguments: + + Str - The string + +Returns: + +--*/ +{ + UINTN Length; + + *Data = 0; + Length = sizeof (UINT64); + HexStringToBuf ((UINT8 *) Data, &Length, TrimHexStr (Str), NULL); +} + +STATIC +UINTN +Atoi ( + IN CHAR16 *str + ) +/*++ + +Routine Description: + + Convert decimal string to uint + +Arguments: + + Str - The string + +Returns: + +--*/ +{ + UINTN Rvalue; + CHAR16 Char; + UINTN High; + UINTN Low; + + ASSERT (str != NULL); + + High = (UINTN) -1 / 10; + Low = (UINTN) -1 % 10; + // + // skip preceeding white space + // + while (*str && *str == ' ') { + str += 1; + } + // + // convert digits + // + Rvalue = 0; + Char = *(str++); + while (Char) { + if (Char >= '0' && Char <= '9') { + if ((Rvalue > High || Rvalue == High) && (Char - '0' > (INTN) Low)) { + return (UINTN) -1; + } + + Rvalue = (Rvalue * 10) + Char - '0'; + } else { + break; + } + + Char = *(str++); + } + + return Rvalue; +} + +STATIC +EFI_STATUS +StrToBuf ( + OUT UINT8 *Buf, + IN UINTN BufferLength, + IN CHAR16 *Str + ) +{ + UINTN Index; + UINTN StrLength; + UINT8 Digit; + UINT8 Byte; + + // + // Two hex char make up one byte + // + StrLength = BufferLength * sizeof (CHAR16); + + for(Index = 0; Index < StrLength; Index++, Str++) { + + IsHexDigit (&Digit, *Str); + + // + // For odd charaters, write the upper nibble for each buffer byte, + // and for even characters, the lower nibble. + // + if ((Index & 1) == 0) { + Byte = (UINT8) (Digit << 4); + } else { + Byte = Buf[Index / 2]; + Byte &= 0xF0; + Byte = (UINT8) (Byte | Digit); + } + + Buf[Index / 2] = Byte; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +StrToGuid ( + IN CHAR16 *Str, + OUT EFI_GUID *Guid + ) +{ + UINTN BufferLength; + UINTN ConvertedStrLen; + EFI_STATUS Status; + + BufferLength = sizeof (Guid->Data1); + Status = HexStringToBuf ((UINT8 *) &Guid->Data1, &BufferLength, Str, &ConvertedStrLen); + if (EFI_ERROR (Status)) { + return Status; + } + Str += ConvertedStrLen; + if (IS_HYPHEN (*Str)) { + Str++; + } else { + return EFI_UNSUPPORTED; + } + + BufferLength = sizeof (Guid->Data2); + Status = HexStringToBuf ((UINT8 *) &Guid->Data2, &BufferLength, Str, &ConvertedStrLen); + if (EFI_ERROR (Status)) { + return Status; + } + Str += ConvertedStrLen; + if (IS_HYPHEN (*Str)) { + Str++; + } else { + return EFI_UNSUPPORTED; + } + + BufferLength = sizeof (Guid->Data3); + Status = HexStringToBuf ((UINT8 *) &Guid->Data3, &BufferLength, Str, &ConvertedStrLen); + if (EFI_ERROR (Status)) { + return Status; + } + Str += ConvertedStrLen; + if (IS_HYPHEN (*Str)) { + Str++; + } else { + return EFI_UNSUPPORTED; + } + + StrToBuf (&Guid->Data4[0], 2, Str); + // + // Skip 2 byte hex chars + // + Str += 2 * 2; + + if (IS_HYPHEN (*Str)) { + Str++; + } else { + return EFI_UNSUPPORTED; + } + StrToBuf (&Guid->Data4[2], 6, Str); + + return EFI_SUCCESS; +} + +STATIC +VOID +StrToIPv4Addr ( + IN OUT CHAR16 **Str, + OUT EFI_IPv4_ADDRESS *IPv4Addr + ) +{ + UINTN Index; + + for (Index = 0; Index < 4; Index++) { + IPv4Addr->Addr[Index] = (UINT8) Atoi (SplitStr (Str, L'.')); + } +} + +STATIC +VOID +StrToIPv6Addr ( + IN OUT CHAR16 **Str, + OUT EFI_IPv6_ADDRESS *IPv6Addr + ) +{ + UINTN Index; + UINT16 Data; + + for (Index = 0; Index < 8; Index++) { + Data = (UINT16) Xtoi (SplitStr (Str, L':')); + IPv6Addr->Addr[Index * 2] = (UINT8) (Data >> 8); + IPv6Addr->Addr[Index * 2 + 1] = (UINT8) (Data & 0xff); + } +} + +STATIC +VOID +StrToAscii ( + IN CHAR16 *Str, + IN OUT CHAR8 **AsciiStr + ) +{ + CHAR8 *Dest; + + Dest = *AsciiStr; + while (!IS_NULL (*Str)) { + *(Dest++) = (CHAR8) *(Str++); + } + *Dest = 0; + + // + // Return the string next to it + // + *AsciiStr = Dest + 1; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPci ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *FunctionStr; + CHAR16 *DeviceStr; + PCI_DEVICE_PATH *Pci; + + FunctionStr = GetNextParamStr (&TextDeviceNode); + DeviceStr = GetNextParamStr (&TextDeviceNode); + Pci = (PCI_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_PCI_DP, + sizeof (PCI_DEVICE_PATH) + ); + + Pci->Function = (UINT8) Xtoi (FunctionStr); + Pci->Device = (UINT8) Xtoi (DeviceStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Pci; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPcCard ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *FunctionNumberStr; + PCCARD_DEVICE_PATH *Pccard; + + FunctionNumberStr = GetNextParamStr (&TextDeviceNode); + Pccard = (PCCARD_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_PCCARD_DP, + sizeof (PCCARD_DEVICE_PATH) + ); + + Pccard->FunctionNumber = (UINT8) Xtoi (FunctionNumberStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Pccard; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMemoryMapped ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *StartingAddressStr; + CHAR16 *EndingAddressStr; + MEMMAP_DEVICE_PATH *MemMap; + + StartingAddressStr = GetNextParamStr (&TextDeviceNode); + EndingAddressStr = GetNextParamStr (&TextDeviceNode); + MemMap = (MEMMAP_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + sizeof (MEMMAP_DEVICE_PATH) + ); + + MemMap->MemoryType = 0; + + Xtoi64 (StartingAddressStr, &MemMap->StartingAddress); + Xtoi64 (EndingAddressStr, &MemMap->EndingAddress); + + return (EFI_DEVICE_PATH_PROTOCOL *) MemMap; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +ConvertFromTextVendor ( + IN CHAR16 *TextDeviceNode, + IN UINT8 Type, + IN UINT8 SubType + ) +{ + CHAR16 *GuidStr; + CHAR16 *DataStr; + UINTN Length; + VENDOR_DEVICE_PATH *Vendor; + + GuidStr = GetNextParamStr (&TextDeviceNode); + + DataStr = GetNextParamStr (&TextDeviceNode); + Length = StrLen (DataStr); + // + // Two hex characters make up 1 buffer byte + // + Length = (Length + 1) / 2; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + Type, + SubType, + sizeof (VENDOR_DEVICE_PATH) + (UINT16) Length + ); + + StrToGuid (GuidStr, &Vendor->Guid); + StrToBuf (((UINT8 *) Vendor) + sizeof (VENDOR_DEVICE_PATH), Length, DataStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenHw ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextVendor ( + TextDeviceNode, + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP + ); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextCtrl ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *ControllerStr; + CONTROLLER_DEVICE_PATH *Controller; + + ControllerStr = GetNextParamStr (&TextDeviceNode); + Controller = (CONTROLLER_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_CONTROLLER_DP, + sizeof (CONTROLLER_DEVICE_PATH) + ); + Controller->ControllerNumber = (UINT32) Xtoi (ControllerStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Controller; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpi ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *HIDStr; + CHAR16 *UIDStr; + ACPI_HID_DEVICE_PATH *Acpi; + + HIDStr = GetNextParamStr (&TextDeviceNode); + UIDStr = GetNextParamStr (&TextDeviceNode); + Acpi = (ACPI_HID_DEVICE_PATH *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_DP, + sizeof (ACPI_HID_DEVICE_PATH) + ); + + if ((HIDStr[0] == L'P') && (HIDStr[1] == L'N') && (HIDStr[2] == L'P')) { + HIDStr += 3; + } + + Acpi->HID = EISA_PNP_ID (Xtoi (HIDStr)); + Acpi->UID = (UINT32) Xtoi (UIDStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Acpi; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +ConvertFromTextAcpi ( + IN CHAR16 *TextDeviceNode, + IN UINT32 Hid + ) +{ + CHAR16 *UIDStr; + ACPI_HID_DEVICE_PATH *Acpi; + + UIDStr = GetNextParamStr (&TextDeviceNode); + Acpi = (ACPI_HID_DEVICE_PATH *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_DP, + sizeof (ACPI_HID_DEVICE_PATH) + ); + + Acpi->HID = Hid; + Acpi->UID = (UINT32) Xtoi (UIDStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Acpi; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPciRoot ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x0a0341d0); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFloppy ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x060441d0); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextKeyboard ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x030141d0); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextSerial ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x050141d0); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextParallelPort ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x040141d0); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpiEx ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *HIDStr; + CHAR16 *CIDStr; + CHAR16 *UIDStr; + CHAR16 *HIDSTRStr; + CHAR16 *CIDSTRStr; + CHAR16 *UIDSTRStr; + CHAR8 *AsciiStr; + UINT16 Length; + ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR *AcpiExt; + + HIDStr = GetNextParamStr (&TextDeviceNode); + CIDStr = GetNextParamStr (&TextDeviceNode); + UIDStr = GetNextParamStr (&TextDeviceNode); + HIDSTRStr = GetNextParamStr (&TextDeviceNode); + CIDSTRStr = GetNextParamStr (&TextDeviceNode); + UIDSTRStr = GetNextParamStr (&TextDeviceNode); + + Length = (UINT16) (sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + StrLen (HIDSTRStr) + 1); + Length = (UINT16) (Length + StrLen (UIDSTRStr) + 1); + Length = (UINT16) (Length + StrLen (CIDSTRStr) + 1); + AcpiExt = (ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_EXTENDED_DP, + Length + ); + + if ((HIDStr[0] == L'P') && (HIDStr[1] == L'N') && (HIDStr[2] == L'P')) { + HIDStr += 3; + AcpiExt->HID = EISA_PNP_ID (Xtoi (HIDStr)); + } else { + AcpiExt->HID = (UINT32) Xtoi (HIDStr); + } + + AcpiExt->UID = (UINT32) Xtoi (UIDStr); + AcpiExt->CID = (UINT32) Xtoi (CIDStr); + + AsciiStr = AcpiExt->HidUidCidStr; + StrToAscii (HIDSTRStr, &AsciiStr); + StrToAscii (UIDSTRStr, &AsciiStr); + StrToAscii (CIDSTRStr, &AsciiStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) AcpiExt; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpiExp ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *HIDStr; + CHAR16 *CIDStr; + CHAR16 *UIDSTRStr; + CHAR8 *AsciiStr; + UINT16 Length; + ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR *AcpiExt; + + HIDStr = GetNextParamStr (&TextDeviceNode); + CIDStr = GetNextParamStr (&TextDeviceNode); + UIDSTRStr = GetNextParamStr (&TextDeviceNode); + Length = sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + (UINT16) StrLen (UIDSTRStr) + 3; + AcpiExt = (ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_EXTENDED_DP, + Length + ); + + if ((HIDStr[0] == L'P') && (HIDStr[1] == L'N') && (HIDStr[2] == L'P')) { + HIDStr += 3; + AcpiExt->HID = EISA_PNP_ID (Xtoi (HIDStr)); + } else { + AcpiExt->HID = (UINT32) Xtoi (HIDStr); + } + + AcpiExt->UID = 0; + AcpiExt->CID = (UINT32) Xtoi (CIDStr); + + AsciiStr = AcpiExt->HidUidCidStr; + // + // HID string is NULL + // + *AsciiStr = 0; + // + // Convert UID string + // + AsciiStr++; + StrToAscii (UIDSTRStr, &AsciiStr); + // + // CID string is NULL + // + *AsciiStr = 0; + + return (EFI_DEVICE_PATH_PROTOCOL *) AcpiExt; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAta ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PrimarySecondaryStr; + CHAR16 *SlaveMasterStr; + CHAR16 *LunStr; + ATAPI_DEVICE_PATH *Atapi; + + Atapi = (ATAPI_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_ATAPI_DP, + sizeof (ATAPI_DEVICE_PATH) + ); + + PrimarySecondaryStr = GetNextParamStr (&TextDeviceNode); + SlaveMasterStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + + Atapi->PrimarySecondary = (UINT8) ((StrCmp (PrimarySecondaryStr, L"Primary") == 0) ? 0 : 1); + Atapi->SlaveMaster = (UINT8) ((StrCmp (SlaveMasterStr, L"Master") == 0) ? 0 : 1); + Atapi->Lun = (UINT16) Xtoi (LunStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Atapi; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextScsi ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PunStr; + CHAR16 *LunStr; + SCSI_DEVICE_PATH *Scsi; + + PunStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + Scsi = (SCSI_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_SCSI_DP, + sizeof (SCSI_DEVICE_PATH) + ); + + Scsi->Pun = (UINT16) Xtoi (PunStr); + Scsi->Lun = (UINT16) Xtoi (LunStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Scsi; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFibre ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *WWNStr; + CHAR16 *LunStr; + FIBRECHANNEL_DEVICE_PATH *Fibre; + + WWNStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + Fibre = (FIBRECHANNEL_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_FIBRECHANNEL_DP, + sizeof (FIBRECHANNEL_DEVICE_PATH) + ); + + Fibre->Reserved = 0; + Xtoi64 (WWNStr, &Fibre->WWN); + Xtoi64 (LunStr, &Fibre->Lun); + + return (EFI_DEVICE_PATH_PROTOCOL *) Fibre; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromText1394 ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *GuidStr; + F1394_DEVICE_PATH *F1394; + + GuidStr = GetNextParamStr (&TextDeviceNode); + F1394 = (F1394_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_1394_DP, + sizeof (F1394_DEVICE_PATH) + ); + + F1394->Reserved = 0; + Xtoi64 (GuidStr, &F1394->Guid); + + return (EFI_DEVICE_PATH_PROTOCOL *) F1394; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsb ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PortStr; + CHAR16 *InterfaceStr; + USB_DEVICE_PATH *Usb; + + PortStr = GetNextParamStr (&TextDeviceNode); + InterfaceStr = GetNextParamStr (&TextDeviceNode); + Usb = (USB_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_USB_DP, + sizeof (USB_DEVICE_PATH) + ); + + Usb->ParentPortNumber = (UINT8) Xtoi (PortStr); + Usb->InterfaceNumber = (UINT8) Xtoi (InterfaceStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Usb; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextI2O ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *TIDStr; + I2O_DEVICE_PATH *I2O; + + TIDStr = GetNextParamStr (&TextDeviceNode); + I2O = (I2O_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_I2O_DP, + sizeof (I2O_DEVICE_PATH) + ); + + I2O->Tid = (UINT32) Xtoi (TIDStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) I2O; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextInfiniband ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *FlagsStr; + CHAR16 *GuidStr; + CHAR16 *SidStr; + CHAR16 *TidStr; + CHAR16 *DidStr; + EFI_GUID PortGid; + INFINIBAND_DEVICE_PATH *InfiniBand; + + FlagsStr = GetNextParamStr (&TextDeviceNode); + GuidStr = GetNextParamStr (&TextDeviceNode); + SidStr = GetNextParamStr (&TextDeviceNode); + TidStr = GetNextParamStr (&TextDeviceNode); + DidStr = GetNextParamStr (&TextDeviceNode); + InfiniBand = (INFINIBAND_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_INFINIBAND_DP, + sizeof (INFINIBAND_DEVICE_PATH) + ); + + InfiniBand->ResourceFlags = (UINT32) Xtoi (FlagsStr); + StrToGuid (GuidStr, &PortGid); + CopyMem (InfiniBand->PortGid, &PortGid, sizeof (EFI_GUID)); + Xtoi64 (SidStr, &InfiniBand->ServiceId); + Xtoi64 (TidStr, &InfiniBand->TargetPortId); + Xtoi64 (DidStr, &InfiniBand->DeviceId); + + return (EFI_DEVICE_PATH_PROTOCOL *) InfiniBand; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenMsg ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextVendor ( + TextDeviceNode, + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP + ); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenPcAnsi ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + sizeof (VENDOR_DEVICE_PATH)); + CopyGuid (&Vendor->Guid, &gEfiPcAnsiGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenVt100 ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + sizeof (VENDOR_DEVICE_PATH)); + CopyGuid (&Vendor->Guid, &gEfiVT100Guid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenVt100Plus ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + sizeof (VENDOR_DEVICE_PATH)); + CopyGuid (&Vendor->Guid, &gEfiVT100PlusGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenUtf8 ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + sizeof (VENDOR_DEVICE_PATH)); + CopyGuid (&Vendor->Guid, &gEfiVTUTF8Guid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUartFlowCtrl ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *ValueStr; + UART_FLOW_CONTROL_DEVICE_PATH *UartFlowControl; + + ValueStr = GetNextParamStr (&TextDeviceNode); + UartFlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + sizeof (UART_FLOW_CONTROL_DEVICE_PATH) + ); + + CopyGuid (&UartFlowControl->Guid, &mEfiDevicePathMessagingUartFlowControlGuid); + if (StrCmp (ValueStr, L"XonXoff") == 0) { + UartFlowControl->FlowControlMap = 2; + } else if (StrCmp (ValueStr, L"Hardware") == 0) { + UartFlowControl->FlowControlMap = 1; + } else { + UartFlowControl->FlowControlMap = 0; + } + + return (EFI_DEVICE_PATH_PROTOCOL *) UartFlowControl; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextSAS ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *AddressStr; + CHAR16 *LunStr; + CHAR16 *RTPStr; + CHAR16 *SASSATAStr; + CHAR16 *LocationStr; + CHAR16 *ConnectStr; + CHAR16 *DriveBayStr; + CHAR16 *ReservedStr; + UINT16 Info; + SAS_DEVICE_PATH *Sas; + + AddressStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + RTPStr = GetNextParamStr (&TextDeviceNode); + SASSATAStr = GetNextParamStr (&TextDeviceNode); + LocationStr = GetNextParamStr (&TextDeviceNode); + ConnectStr = GetNextParamStr (&TextDeviceNode); + DriveBayStr = GetNextParamStr (&TextDeviceNode); + ReservedStr = GetNextParamStr (&TextDeviceNode); + Info = 0x0000; + Sas = (SAS_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + sizeof (SAS_DEVICE_PATH) + ); + + CopyGuid (&Sas->Guid, &mEfiDevicePathMessagingSASGuid); + Xtoi64 (AddressStr, &Sas->SasAddress); + Xtoi64 (LunStr, &Sas->Lun); + Sas->RelativeTargetPort = (UINT16) Xtoi (RTPStr); + if (StrCmp (SASSATAStr, L"NoTopology") == 0) + ; + else { + if (StrCmp (DriveBayStr, L"0") == 0) { + Info |= 0x0001; + } else { + Info |= 0x0002; + Info |= (Xtoi (DriveBayStr) << 8); + } + + if (StrCmp (SASSATAStr, L"SATA") == 0) { + Info |= 0x0010; + } + + if (StrCmp (LocationStr, L"External") == 0) { + Info |= 0x0020; + } + + if (StrCmp (ConnectStr, L"Expanded") == 0) { + Info |= 0x0040; + } + } + + Sas->DeviceTopology = Info; + Sas->Reserved = (UINT32) Xtoi (ReservedStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Sas; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextDebugPort ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEFINED_MESSAGING_DEVICE_PATH *Vend; + + Vend = (VENDOR_DEFINED_MESSAGING_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + sizeof (VENDOR_DEFINED_MESSAGING_DEVICE_PATH) + ); + + CopyGuid (&Vend->Guid, &gEfiDebugPortProtocolGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vend; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMAC ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *AddressStr; + CHAR16 *IfTypeStr; + UINTN Length; + MAC_ADDR_DEVICE_PATH *MAC; + + AddressStr = GetNextParamStr (&TextDeviceNode); + IfTypeStr = GetNextParamStr (&TextDeviceNode); + MAC = (MAC_ADDR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_MAC_ADDR_DP, + sizeof (MAC_ADDR_DEVICE_PATH) + ); + + MAC->IfType = (UINT8) Xtoi (IfTypeStr); + + Length = sizeof (EFI_MAC_ADDRESS); + StrToBuf (&MAC->MacAddress.Addr[0], Length, AddressStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) MAC; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextIPv4 ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *RemoteIPStr; + CHAR16 *ProtocolStr; + CHAR16 *TypeStr; + CHAR16 *LocalIPStr; + IPv4_DEVICE_PATH *IPv4; + + RemoteIPStr = GetNextParamStr (&TextDeviceNode); + ProtocolStr = GetNextParamStr (&TextDeviceNode); + TypeStr = GetNextParamStr (&TextDeviceNode); + LocalIPStr = GetNextParamStr (&TextDeviceNode); + IPv4 = (IPv4_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_IPv4_DP, + sizeof (IPv4_DEVICE_PATH) + ); + + StrToIPv4Addr (&RemoteIPStr, &IPv4->RemoteIpAddress); + IPv4->Protocol = (UINT16) ((StrCmp (ProtocolStr, L"UDP") == 0) ? 0 : 1); + if (StrCmp (TypeStr, L"Static") == 0) { + IPv4->StaticIpAddress = TRUE; + } else { + IPv4->StaticIpAddress = FALSE; + } + + StrToIPv4Addr (&LocalIPStr, &IPv4->LocalIpAddress); + + IPv4->LocalPort = 0; + IPv4->RemotePort = 0; + + return (EFI_DEVICE_PATH_PROTOCOL *) IPv4; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextIPv6 ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *RemoteIPStr; + CHAR16 *ProtocolStr; + CHAR16 *TypeStr; + CHAR16 *LocalIPStr; + IPv6_DEVICE_PATH *IPv6; + + RemoteIPStr = GetNextParamStr (&TextDeviceNode); + ProtocolStr = GetNextParamStr (&TextDeviceNode); + TypeStr = GetNextParamStr (&TextDeviceNode); + LocalIPStr = GetNextParamStr (&TextDeviceNode); + IPv6 = (IPv6_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_IPv6_DP, + sizeof (IPv6_DEVICE_PATH) + ); + + StrToIPv6Addr (&RemoteIPStr, &IPv6->RemoteIpAddress); + IPv6->Protocol = (UINT16) ((StrCmp (ProtocolStr, L"UDP") == 0) ? 0 : 1); + if (StrCmp (TypeStr, L"Static") == 0) { + IPv6->StaticIpAddress = TRUE; + } else { + IPv6->StaticIpAddress = FALSE; + } + + StrToIPv6Addr (&LocalIPStr, &IPv6->LocalIpAddress); + + IPv6->LocalPort = 0; + IPv6->RemotePort = 0; + + return (EFI_DEVICE_PATH_PROTOCOL *) IPv6; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUart ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *BaudStr; + CHAR16 *DataBitsStr; + CHAR16 *ParityStr; + CHAR16 *StopBitsStr; + UART_DEVICE_PATH *Uart; + + BaudStr = GetNextParamStr (&TextDeviceNode); + DataBitsStr = GetNextParamStr (&TextDeviceNode); + ParityStr = GetNextParamStr (&TextDeviceNode); + StopBitsStr = GetNextParamStr (&TextDeviceNode); + Uart = (UART_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_UART_DP, + sizeof (UART_DEVICE_PATH) + ); + + Uart->BaudRate = (StrCmp (BaudStr, L"DEFAULT") == 0) ? 115200 : Atoi (BaudStr); + Uart->DataBits = (UINT8) ((StrCmp (DataBitsStr, L"DEFAULT") == 0) ? 8 : Atoi (DataBitsStr)); + switch (*ParityStr) { + case L'D': + Uart->Parity = 0; + break; + + case L'N': + Uart->Parity = 1; + break; + + case L'E': + Uart->Parity = 2; + break; + + case L'O': + Uart->Parity = 3; + break; + + case L'M': + Uart->Parity = 4; + break; + + case L'S': + Uart->Parity = 5; + + default: + Uart->Parity = 0xff; + } + + if (StrCmp (StopBitsStr, L"D") == 0) { + Uart->StopBits = (UINT8) 0; + } else if (StrCmp (StopBitsStr, L"1") == 0) { + Uart->StopBits = (UINT8) 1; + } else if (StrCmp (StopBitsStr, L"1.5") == 0) { + Uart->StopBits = (UINT8) 2; + } else if (StrCmp (StopBitsStr, L"2") == 0) { + Uart->StopBits = (UINT8) 3; + } else { + Uart->StopBits = 0xff; + } + + return (EFI_DEVICE_PATH_PROTOCOL *) Uart; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +ConvertFromTextUsbClass ( + IN CHAR16 *TextDeviceNode, + IN USB_CLASS_TEXT *UsbClassText + ) +{ + CHAR16 *VIDStr; + CHAR16 *PIDStr; + CHAR16 *ClassStr; + CHAR16 *SubClassStr; + CHAR16 *ProtocolStr; + USB_CLASS_DEVICE_PATH *UsbClass; + + UsbClass = (USB_CLASS_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_USB_CLASS_DP, + sizeof (USB_CLASS_DEVICE_PATH) + ); + + VIDStr = GetNextParamStr (&TextDeviceNode); + PIDStr = GetNextParamStr (&TextDeviceNode); + if (UsbClassText->ClassExist) { + ClassStr = GetNextParamStr (&TextDeviceNode); + UsbClass->DeviceClass = (UINT8) Xtoi (ClassStr); + } else { + UsbClass->DeviceClass = UsbClassText->Class; + } + if (UsbClassText->SubClassExist) { + SubClassStr = GetNextParamStr (&TextDeviceNode); + UsbClass->DeviceSubClass = (UINT8) Xtoi (SubClassStr); + } else { + UsbClass->DeviceSubClass = UsbClassText->SubClass; + } + + ProtocolStr = GetNextParamStr (&TextDeviceNode); + + UsbClass->VendorId = (UINT16) Xtoi (VIDStr); + UsbClass->ProductId = (UINT16) Xtoi (PIDStr); + UsbClass->DeviceProtocol = (UINT8) Xtoi (ProtocolStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) UsbClass; +} + + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbClass ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = TRUE; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbAudio ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_AUDIO; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbCDCControl ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_CDCCONTROL; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbHID ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_HID; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbImage ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_IMAGE; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbPrinter ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_PRINTER; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbMassStorage ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_MASS_STORAGE; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbHub ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_HUB; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbCDCData ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_CDCDATA; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbSmartCard ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_SMART_CARD; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbVideo ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_VIDEO; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbDiagnostic ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_DIAGNOSTIC; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbWireless ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_WIRELESS; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbDeviceFirmwareUpdate ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_RESERVE; + UsbClassText.SubClassExist = FALSE; + UsbClassText.SubClass = USB_SUBCLASS_FW_UPDATE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbIrdaBridge ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_RESERVE; + UsbClassText.SubClassExist = FALSE; + UsbClassText.SubClass = USB_SUBCLASS_IRDA_BRIDGE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbTestAndMeasurement ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_RESERVE; + UsbClassText.SubClassExist = FALSE; + UsbClassText.SubClass = USB_SUBCLASS_TEST; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbWwid ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *VIDStr; + CHAR16 *PIDStr; + CHAR16 *InterfaceNumStr; + USB_WWID_DEVICE_PATH *UsbWwid; + + VIDStr = GetNextParamStr (&TextDeviceNode); + PIDStr = GetNextParamStr (&TextDeviceNode); + InterfaceNumStr = GetNextParamStr (&TextDeviceNode); + UsbWwid = (USB_WWID_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_USB_WWID_DP, + sizeof (USB_WWID_DEVICE_PATH) + ); + + UsbWwid->VendorId = (UINT16) Xtoi (VIDStr); + UsbWwid->ProductId = (UINT16) Xtoi (PIDStr); + UsbWwid->InterfaceNumber = (UINT16) Xtoi (InterfaceNumStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) UsbWwid; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUnit ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *LunStr; + DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit; + + LunStr = GetNextParamStr (&TextDeviceNode); + LogicalUnit = (DEVICE_LOGICAL_UNIT_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_DEVICE_LOGICAL_UNIT_DP, + sizeof (DEVICE_LOGICAL_UNIT_DEVICE_PATH) + ); + + LogicalUnit->Lun = (UINT8) Xtoi (LunStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) LogicalUnit; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextiSCSI ( + IN CHAR16 *TextDeviceNode + ) +{ + UINT16 Options; + CHAR16 *NameStr; + CHAR16 *PortalGroupStr; + CHAR16 *LunStr; + CHAR16 *HeaderDigestStr; + CHAR16 *DataDigestStr; + CHAR16 *AuthenticationStr; + CHAR16 *ProtocolStr; + ISCSI_DEVICE_PATH_WITH_NAME *iSCSI; + + NameStr = GetNextParamStr (&TextDeviceNode); + PortalGroupStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + HeaderDigestStr = GetNextParamStr (&TextDeviceNode); + DataDigestStr = GetNextParamStr (&TextDeviceNode); + AuthenticationStr = GetNextParamStr (&TextDeviceNode); + ProtocolStr = GetNextParamStr (&TextDeviceNode); + iSCSI = (ISCSI_DEVICE_PATH_WITH_NAME *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_ISCSI_DP, + sizeof (ISCSI_DEVICE_PATH_WITH_NAME) + (UINT16) (StrLen (NameStr) * 2) + ); + + StrCpy (iSCSI->iSCSITargetName, NameStr); + iSCSI->TargetPortalGroupTag = (UINT16) Xtoi (PortalGroupStr); + Xtoi64 (LunStr, &iSCSI->Lun); + + Options = 0x0000; + if (StrCmp (HeaderDigestStr, L"CRC32C") == 0) { + Options |= 0x0002; + } + + if (StrCmp (DataDigestStr, L"CRC32C") == 0) { + Options |= 0x0008; + } + + if (StrCmp (AuthenticationStr, L"None") == 0) { + Options |= 0x0800; + } + + if (StrCmp (AuthenticationStr, L"CHAP_UNI") == 0) { + Options |= 0x1000; + } + + iSCSI->LoginOption = (UINT16) Options; + + iSCSI->NetworkProtocol = (UINT16) StrCmp (ProtocolStr, L"TCP"); + iSCSI->Reserved = (UINT16) 0; + + return (EFI_DEVICE_PATH_PROTOCOL *) iSCSI; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextHD ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PartitionStr; + CHAR16 *TypeStr; + CHAR16 *SignatureStr; + CHAR16 *StartStr; + CHAR16 *SizeStr; + UINT32 Signature32; + EFI_GUID SignatureGuid; + HARDDRIVE_DEVICE_PATH *Hd; + + PartitionStr = GetNextParamStr (&TextDeviceNode); + TypeStr = GetNextParamStr (&TextDeviceNode); + SignatureStr = GetNextParamStr (&TextDeviceNode); + StartStr = GetNextParamStr (&TextDeviceNode); + SizeStr = GetNextParamStr (&TextDeviceNode); + Hd = (HARDDRIVE_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_HARDDRIVE_DP, + sizeof (HARDDRIVE_DEVICE_PATH) + ); + + Hd->PartitionNumber = (UINT32) Atoi (PartitionStr); + + ZeroMem (Hd->Signature, 16); + Hd->MBRType = (UINT8) 0; + + if (StrCmp (TypeStr, L"None") == 0) { + Hd->SignatureType = (UINT8) 0; + } else if (StrCmp (TypeStr, L"MBR") == 0) { + Hd->SignatureType = SIGNATURE_TYPE_MBR; + Hd->MBRType = 0x01; + + Signature32 = (UINT32) Xtoi (SignatureStr); + CopyMem (Hd->Signature, &Signature32, sizeof (UINT32)); + } else if (StrCmp (TypeStr, L"GUID") == 0) { + Hd->SignatureType = SIGNATURE_TYPE_GUID; + Hd->MBRType = 0x02; + + StrToGuid (SignatureStr, &SignatureGuid); + CopyMem (Hd->Signature, &SignatureGuid, sizeof (EFI_GUID)); + } else { + Hd->SignatureType = 0xff; + + } + + Xtoi64 (StartStr, &Hd->PartitionStart); + Xtoi64 (SizeStr, &Hd->PartitionSize); + + return (EFI_DEVICE_PATH_PROTOCOL *) Hd; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextCDROM ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *EntryStr; + CHAR16 *StartStr; + CHAR16 *SizeStr; + CDROM_DEVICE_PATH *CDROM; + + EntryStr = GetNextParamStr (&TextDeviceNode); + StartStr = GetNextParamStr (&TextDeviceNode); + SizeStr = GetNextParamStr (&TextDeviceNode); + CDROM = (CDROM_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_CDROM_DP, + sizeof (CDROM_DEVICE_PATH) + ); + + CDROM->BootEntry = (UINT32) Xtoi (EntryStr); + Xtoi64 (StartStr, &CDROM->PartitionStart); + Xtoi64 (SizeStr, &CDROM->PartitionSize); + + return (EFI_DEVICE_PATH_PROTOCOL *) CDROM; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenMEDIA ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextVendor ( + TextDeviceNode, + MEDIA_DEVICE_PATH, + MEDIA_VENDOR_DP + ); +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFilePath ( + IN CHAR16 *TextDeviceNode + ) +{ + FILEPATH_DEVICE_PATH *File; + + File = (FILEPATH_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_FILEPATH_DP, + sizeof (FILEPATH_DEVICE_PATH) + (UINT16) (StrLen (TextDeviceNode) * 2) + ); + + StrCpy (File->PathName, TextDeviceNode); + + return (EFI_DEVICE_PATH_PROTOCOL *) File; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMedia ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *GuidStr; + MEDIA_PROTOCOL_DEVICE_PATH *Media; + + GuidStr = GetNextParamStr (&TextDeviceNode); + Media = (MEDIA_PROTOCOL_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_PROTOCOL_DP, + sizeof (MEDIA_PROTOCOL_DEVICE_PATH) + ); + + StrToGuid (GuidStr, &Media->Protocol); + + return (EFI_DEVICE_PATH_PROTOCOL *) Media; +} + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextBBS ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *TypeStr; + CHAR16 *IdStr; + CHAR16 *FlagsStr; + UINT8 *AsciiStr; + BBS_BBS_DEVICE_PATH *Bbs; + + TypeStr = GetNextParamStr (&TextDeviceNode); + IdStr = GetNextParamStr (&TextDeviceNode); + FlagsStr = GetNextParamStr (&TextDeviceNode); + Bbs = (BBS_BBS_DEVICE_PATH *) CreateDeviceNode ( + BBS_DEVICE_PATH, + BBS_BBS_DP, + sizeof (BBS_BBS_DEVICE_PATH) + (UINT16) (StrLen (IdStr)) + ); + + if (StrCmp (TypeStr, L"Floppy") == 0) { + Bbs->DeviceType = BBS_TYPE_FLOPPY; + } else if (StrCmp (TypeStr, L"HD") == 0) { + Bbs->DeviceType = BBS_TYPE_HARDDRIVE; + } else if (StrCmp (TypeStr, L"CDROM") == 0) { + Bbs->DeviceType = BBS_TYPE_CDROM; + } else if (StrCmp (TypeStr, L"PCMCIA") == 0) { + Bbs->DeviceType = BBS_TYPE_PCMCIA; + } else if (StrCmp (TypeStr, L"USB") == 0) { + Bbs->DeviceType = BBS_TYPE_USB; + } else if (StrCmp (TypeStr, L"Network") == 0) { + Bbs->DeviceType = BBS_TYPE_EMBEDDED_NETWORK; + } else { + Bbs->DeviceType = BBS_TYPE_UNKNOWN; + } + + AsciiStr = (UINT8 *) Bbs->String; + StrToAscii (IdStr, (CHAR8 **) &AsciiStr); + + Bbs->StatusFlag = (UINT16) Xtoi (FlagsStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Bbs; +} + +GLOBAL_REMOVE_IF_UNREFERENCED DEVICE_PATH_FROM_TEXT_TABLE DevPathFromTextTable[] = { + {L"Pci", DevPathFromTextPci}, + {L"PcCard", DevPathFromTextPcCard}, + {L"MemoryMapped", DevPathFromTextMemoryMapped}, + {L"VenHw", DevPathFromTextVenHw}, + {L"Ctrl", DevPathFromTextCtrl}, + {L"Acpi", DevPathFromTextAcpi}, + {L"PciRoot", DevPathFromTextPciRoot}, + {L"Floppy", DevPathFromTextFloppy}, + {L"Keyboard", DevPathFromTextKeyboard}, + {L"Serial", DevPathFromTextSerial}, + {L"ParallelPort", DevPathFromTextParallelPort}, + {L"AcpiEx", DevPathFromTextAcpiEx}, + {L"AcpiExp", DevPathFromTextAcpiExp}, + {L"Ata", DevPathFromTextAta}, + {L"Scsi", DevPathFromTextScsi}, + {L"Fibre", DevPathFromTextFibre}, + {L"I1394", DevPathFromText1394}, + {L"USB", DevPathFromTextUsb}, + {L"I2O", DevPathFromTextI2O}, + {L"Infiniband", DevPathFromTextInfiniband}, + {L"VenMsg", DevPathFromTextVenMsg}, + {L"VenPcAnsi", DevPathFromTextVenPcAnsi}, + {L"VenVt100", DevPathFromTextVenVt100}, + {L"VenVt100Plus", DevPathFromTextVenVt100Plus}, + {L"VenUtf8", DevPathFromTextVenUtf8}, + {L"UartFlowCtrl", DevPathFromTextUartFlowCtrl}, + {L"SAS", DevPathFromTextSAS}, + {L"DebugPort", DevPathFromTextDebugPort}, + {L"MAC", DevPathFromTextMAC}, + {L"IPv4", DevPathFromTextIPv4}, + {L"IPv6", DevPathFromTextIPv6}, + {L"Uart", DevPathFromTextUart}, + {L"UsbClass", DevPathFromTextUsbClass}, + {L"UsbAudio", DevPathFromTextUsbAudio}, + {L"UsbCDCControl", DevPathFromTextUsbCDCControl}, + {L"UsbHID", DevPathFromTextUsbHID}, + {L"UsbImage", DevPathFromTextUsbImage}, + {L"UsbPrinter", DevPathFromTextUsbPrinter}, + {L"UsbMassStorage", DevPathFromTextUsbMassStorage}, + {L"UsbHub", DevPathFromTextUsbHub}, + {L"UsbCDCData", DevPathFromTextUsbCDCData}, + {L"UsbSmartCard", DevPathFromTextUsbSmartCard}, + {L"UsbVideo", DevPathFromTextUsbVideo}, + {L"UsbDiagnostic", DevPathFromTextUsbDiagnostic}, + {L"UsbWireless", DevPathFromTextUsbWireless}, + {L"UsbDeviceFirmwareUpdate", DevPathFromTextUsbDeviceFirmwareUpdate}, + {L"UsbIrdaBridge", DevPathFromTextUsbIrdaBridge}, + {L"UsbTestAndMeasurement", DevPathFromTextUsbTestAndMeasurement}, + {L"UsbWwid", DevPathFromTextUsbWwid}, + {L"Unit", DevPathFromTextUnit}, + {L"iSCSI", DevPathFromTextiSCSI}, + {L"HD", DevPathFromTextHD}, + {L"CDROM", DevPathFromTextCDROM}, + {L"VenMEDIA", DevPathFromTextVenMEDIA}, + {L"Media", DevPathFromTextMedia}, + {L"BBS", DevPathFromTextBBS}, + {NULL, NULL} +}; + +EFI_DEVICE_PATH_PROTOCOL * +ConvertTextToDeviceNode ( + IN CONST CHAR16 *TextDeviceNode + ) +/*++ + + Routine Description: + Convert text to the binary representation of a device node. + + Arguments: + TextDeviceNode - TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + Returns: + A pointer - Pointer to the EFI device node. + NULL - If TextDeviceNode is NULL or there was insufficient memory or text unsupported. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL * (*DumpNode) (CHAR16 *); + CHAR16 *ParamStr; + EFI_DEVICE_PATH_PROTOCOL *DeviceNode; + CHAR16 *DeviceNodeStr; + UINTN Index; + + if ((TextDeviceNode == NULL) || (IS_NULL (*TextDeviceNode))) { + return NULL; + } + + ParamStr = NULL; + DumpNode = NULL; + DeviceNodeStr = StrDuplicate (TextDeviceNode); + + for (Index = 0; DevPathFromTextTable[Index].Function; Index++) { + ParamStr = GetParamByNodeName (DeviceNodeStr, DevPathFromTextTable[Index].DevicePathNodeText); + if (ParamStr != NULL) { + DumpNode = DevPathFromTextTable[Index].Function; + break; + } + } + + if (DumpNode == NULL) { + // + // A file path + // + DumpNode = DevPathFromTextFilePath; + DeviceNode = DumpNode (DeviceNodeStr); + } else { + DeviceNode = DumpNode (ParamStr); + FreePool (ParamStr); + } + + FreePool (DeviceNodeStr); + + return DeviceNode; +} + +EFI_DEVICE_PATH_PROTOCOL * +ConvertTextToDevicePath ( + IN CONST CHAR16 *TextDevicePath + ) +/*++ + + Routine Description: + Convert text to the binary representation of a device path. + + Arguments: + TextDevicePath - TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device node character. + + Returns: + A pointer - Pointer to the allocated device path. + NULL - If TextDeviceNode is NULL or there was insufficient memory. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL * (*DumpNode) (CHAR16 *); + CHAR16 *ParamStr; + EFI_DEVICE_PATH_PROTOCOL *DeviceNode; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + CHAR16 *DevicePathStr; + CHAR16 *Str; + CHAR16 *DeviceNodeStr; + UINT8 IsInstanceEnd; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + if ((TextDevicePath == NULL) || (IS_NULL (*TextDevicePath))) { + return NULL; + } + + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH); + SetDevicePathEndNode (DevicePath); + + ParamStr = NULL; + DeviceNodeStr = NULL; + DevicePathStr = StrDuplicate (TextDevicePath); + + Str = DevicePathStr; + while ((DeviceNodeStr = GetNextDeviceNodeStr (&Str, &IsInstanceEnd)) != NULL) { + DumpNode = NULL; + for (Index = 0; DevPathFromTextTable[Index].Function; Index++) { + ParamStr = GetParamByNodeName (DeviceNodeStr, DevPathFromTextTable[Index].DevicePathNodeText); + if (ParamStr != NULL) { + DumpNode = DevPathFromTextTable[Index].Function; + break; + } + } + + if (DumpNode == NULL) { + // + // A file path + // + DumpNode = DevPathFromTextFilePath; + DeviceNode = DumpNode (DeviceNodeStr); + } else { + DeviceNode = DumpNode (ParamStr); + FreePool (ParamStr); + } + + NewDevicePath = AppendDeviceNodeProtocolInterface (DevicePath, DeviceNode); + FreePool (DevicePath); + FreePool (DeviceNode); + DevicePath = NewDevicePath; + + if (IsInstanceEnd) { + DeviceNode = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH); + SetDevicePathInstanceEndNode (DeviceNode); + + NewDevicePath = AppendDeviceNodeProtocolInterface (DevicePath, DeviceNode); + FreePool (DevicePath); + FreePool (DeviceNode); + DevicePath = NewDevicePath; + } + } + + FreePool (DevicePathStr); + return DevicePath; +} diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c b/MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c new file mode 100644 index 0000000000..c024ccfba1 --- /dev/null +++ b/MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c @@ -0,0 +1,1503 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DevicePathToText.c + +Abstract: + + DevicePathToText protocol as defined in the UEFI 2.0 specification. + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "DevicePath.h" + +STATIC +EFI_DEVICE_PATH_PROTOCOL * +UnpackDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +/*++ + + Routine Description: + Function unpacks a device path data structure so that all the nodes of a device path + are naturally aligned. + + Arguments: + DevPath - A pointer to a device path data structure + + Returns: + If the memory for the device path is successfully allocated, then a pointer to the + new device path is returned. Otherwise, NULL is returned. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *Src; + EFI_DEVICE_PATH_PROTOCOL *Dest; + EFI_DEVICE_PATH_PROTOCOL *NewPath; + UINTN Size; + + if (DevPath == NULL) { + return NULL; + } + // + // Walk device path and round sizes to valid boundries + // + Src = DevPath; + Size = 0; + for (;;) { + Size += DevicePathNodeLength (Src); + Size += ALIGN_SIZE (Size); + + if (IsDevicePathEnd (Src)) { + break; + } + + Src = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (Src); + } + // + // Allocate space for the unpacked path + // + NewPath = AllocateZeroPool (Size); + if (NewPath != NULL) { + + ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0); + + // + // Copy each node + // + Src = DevPath; + Dest = NewPath; + for (;;) { + Size = DevicePathNodeLength (Src); + CopyMem (Dest, Src, Size); + Size += ALIGN_SIZE (Size); + SetDevicePathNodeLength (Dest, Size); + Dest->Type |= EFI_DP_TYPE_UNPACKED; + Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size); + + if (IsDevicePathEnd (Src)) { + break; + } + + Src = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (Src); + } + } + + return NewPath; +} + +STATIC +VOID * +ReallocatePool ( + IN VOID *OldPool, + IN UINTN OldSize, + IN UINTN NewSize + ) +/*++ + + Routine Description: + Adjusts the size of a previously allocated buffer. + + Arguments: + OldPool - A pointer to the buffer whose size is being adjusted. + OldSize - The size of the current buffer. + NewSize - The size of the new buffer. + + Returns: + EFI_SUCEESS - The requested number of bytes were allocated. + EFI_OUT_OF_RESOURCES - The pool requested could not be allocated. + EFI_INVALID_PARAMETER - The buffer was invalid. + +--*/ +{ + VOID *NewPool; + + NewPool = NULL; + if (NewSize) { + NewPool = AllocateZeroPool (NewSize); + } + + if (OldPool) { + if (NewPool) { + CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize); + } + + FreePool (OldPool); + } + + return NewPool; +} + +STATIC +CHAR16 * +CatPrint ( + IN OUT POOL_PRINT *Str, + IN CHAR16 *Fmt, + ... + ) +/*++ + + Routine Description: + Concatenates a formatted unicode string to allocated pool. + The caller must free the resulting buffer. + + Arguments: + Str - Tracks the allocated pool, size in use, and + amount of pool allocated. + Fmt - The format string + + Returns: + Allocated buffer with the formatted string printed in it. + The caller must free the allocated buffer. The buffer + allocation is not packed. + +--*/ +{ + UINT16 *AppendStr; + VA_LIST Args; + UINTN Size; + + AppendStr = AllocateZeroPool (0x1000); + if (AppendStr == NULL) { + return Str->Str; + } + + VA_START (Args, Fmt); + UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args); + VA_END (Args); + if (NULL == Str->Str) { + Size = StrSize (AppendStr); + Str->Str = AllocateZeroPool (Size); + ASSERT (Str->Str != NULL); + } else { + Size = StrSize (AppendStr) - sizeof (UINT16); + Size = Size + StrSize (Str->Str); + Str->Str = ReallocatePool ( + Str->Str, + StrSize (Str->Str), + Size + ); + ASSERT (Str->Str != NULL); + } + + Str->MaxLen = MAX_CHAR * sizeof (UINT16); + if (Size < Str->MaxLen) { + StrCat (Str->Str, AppendStr); + Str->Len = Size - sizeof (UINT16); + } + + FreePool (AppendStr); + return Str->Str; +} + +STATIC +VOID +DevPathToTextPci ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + PCI_DEVICE_PATH *Pci; + + Pci = DevPath; + CatPrint (Str, L"Pci(%x,%x)", Pci->Function, Pci->Device); +} + +STATIC +VOID +DevPathToTextPccard ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + PCCARD_DEVICE_PATH *Pccard; + + Pccard = DevPath; + CatPrint (Str, L"PcCard(%x)", Pccard->FunctionNumber); +} + +STATIC +VOID +DevPathToTextMemMap ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + MEMMAP_DEVICE_PATH *MemMap; + + MemMap = DevPath; + CatPrint ( + Str, + L"MemoryMapped(%lx,%lx)", + MemMap->StartingAddress, + MemMap->EndingAddress + ); +} + +STATIC +VOID +DevPathToTextVendor ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + VENDOR_DEVICE_PATH *Vendor; + CHAR16 *Type; + UINTN Index; + UINT32 FlowControlMap; + UINT16 Info; + + Vendor = (VENDOR_DEVICE_PATH *) DevPath; + switch (DevicePathType (&Vendor->Header)) { + case HARDWARE_DEVICE_PATH: + Type = L"Hw"; + break; + + case MESSAGING_DEVICE_PATH: + Type = L"Msg"; + if (AllowShortcuts) { + if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) { + CatPrint (Str, L"VenPcAnsi()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) { + CatPrint (Str, L"VenVt100()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) { + CatPrint (Str, L"VenVt100Plus()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) { + CatPrint (Str, L"VenUft8()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &mEfiDevicePathMessagingUartFlowControlGuid)) { + FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap); + switch (FlowControlMap & 0x00000003) { + case 0: + CatPrint (Str, L"UartFlowCtrl(%s)", L"None"); + break; + + case 1: + CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware"); + break; + + case 2: + CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff"); + break; + + default: + break; + } + + return ; + } else if (CompareGuid (&Vendor->Guid, &mEfiDevicePathMessagingSASGuid)) { + CatPrint ( + Str, + L"SAS(%lx,%lx,%x,", + ((SAS_DEVICE_PATH *) Vendor)->SasAddress, + ((SAS_DEVICE_PATH *) Vendor)->Lun, + ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort + ); + Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology); + if ((Info & 0x0f) == 0) { + CatPrint (Str, L"NoTopology,0,0,0,"); + } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) { + CatPrint ( + Str, + L"%s,%s,%s,", + (Info & (0x1 << 4)) ? L"SATA" : L"SAS", + (Info & (0x1 << 5)) ? L"External" : L"Internal", + (Info & (0x1 << 6)) ? L"Expanded" : L"Direct" + ); + if ((Info & 0x0f) == 1) { + CatPrint (Str, L"0,"); + } else { + CatPrint (Str, L"%x,", (Info >> 8) & 0xff); + } + } else { + CatPrint (Str, L"0,0,0,0,"); + } + + CatPrint (Str, L"%x)", ((SAS_DEVICE_PATH *) Vendor)->Reserved); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) { + CatPrint (Str, L"DebugPort()"); + return ; + } else { + return ; + // + // reserved + // + } + } + break; + + case MEDIA_DEVICE_PATH: + Type = L"Media"; + break; + + default: + Type = L"?"; + break; + } + + CatPrint (Str, L"Ven%s(%g,", Type, &Vendor->Guid); + for (Index = 0; Index < DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH); Index++) { + CatPrint (Str, L"%02x", ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]); + } + + CatPrint (Str, L")"); +} + +STATIC +VOID +DevPathToTextController ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + CONTROLLER_DEVICE_PATH *Controller; + + Controller = DevPath; + CatPrint ( + Str, + L"Ctrl(%x)", + Controller->ControllerNumber + ); +} + +STATIC +VOID +DevPathToTextAcpi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + ACPI_HID_DEVICE_PATH *Acpi; + + Acpi = DevPath; + if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + if (AllowShortcuts) { + switch (EISA_ID_TO_NUM (Acpi->HID)) { + case 0x0a03: + CatPrint (Str, L"PciRoot(%x)", Acpi->UID); + break; + + case 0x0604: + CatPrint (Str, L"Floppy(%x)", Acpi->UID); + break; + + case 0x0301: + CatPrint (Str, L"Keyboard(%x)", Acpi->UID); + break; + + case 0x0501: + CatPrint (Str, L"Serial(%x)", Acpi->UID); + break; + + case 0x0401: + CatPrint (Str, L"ParallelPort(%x)", Acpi->UID); + break; + + default: + break; + } + + return ; + } + + CatPrint (Str, L"Acpi(PNP%04x,%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID); + } else { + CatPrint (Str, L"Acpi(%08x,%x)", Acpi->HID, Acpi->UID); + } +} + +#define NextStrA(a) ((UINT8 *) (((UINT8 *) (a)) + AsciiStrLen ((CHAR8 *) (a)) + 1)) + +STATIC +VOID +DevPathToTextExtAcpi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR *AcpiExt; + UINT8 *NextString; + + AcpiExt = DevPath; + + if (AllowShortcuts) { + NextString = NextStrA (AcpiExt->HidUidCidStr); + if ((*(AcpiExt->HidUidCidStr) == '\0') && + (*(NextStrA (NextString)) == '\0') && + (AcpiExt->UID == 0) + ) { + if ((AcpiExt->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + CatPrint ( + Str, + L"AcpiExp(PNP%04x,%x,%a)", + EISA_ID_TO_NUM (AcpiExt->HID), + AcpiExt->CID, + NextStrA (AcpiExt->HidUidCidStr) + ); + } else { + CatPrint ( + Str, + L"AcpiExp(%08x,%x,%a)", + AcpiExt->HID, + AcpiExt->CID, + NextStrA (AcpiExt->HidUidCidStr) + ); + } + } + return ; + } + + NextString = NextStrA (AcpiExt->HidUidCidStr); + NextString = NextStrA (NextString); + if ((AcpiExt->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + CatPrint ( + Str, + L"AcpiEx(PNP%04x,%x,%x,%a,%a,%a)", + EISA_ID_TO_NUM (AcpiExt->HID), + AcpiExt->CID, + AcpiExt->UID, + AcpiExt->HidUidCidStr, + NextString, + NextStrA (AcpiExt->HidUidCidStr) + ); + } else { + CatPrint ( + Str, + L"AcpiEx(%08x,%x,%x,%a,%a,%a)", + AcpiExt->HID, + AcpiExt->CID, + AcpiExt->UID, + AcpiExt->HidUidCidStr, + NextString, + NextStrA (AcpiExt->HidUidCidStr) + ); + } +} + +STATIC +VOID +DevPathToTextAtapi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + ATAPI_DEVICE_PATH *Atapi; + + Atapi = DevPath; + + if (DisplayOnly) { + CatPrint (Str, L"Ata(%x)", Atapi->Lun); + } else { + CatPrint ( + Str, + L"Ata(%s,%s,%x)", + Atapi->PrimarySecondary ? L"Secondary" : L"Primary", + Atapi->SlaveMaster ? L"Slave" : L"Master", + Atapi->Lun + ); + } +} + +STATIC +VOID +DevPathToTextScsi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + SCSI_DEVICE_PATH *Scsi; + + Scsi = DevPath; + CatPrint (Str, L"Scsi(%x,%x)", Scsi->Pun, Scsi->Lun); +} + +STATIC +VOID +DevPathToTextFibre ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + FIBRECHANNEL_DEVICE_PATH *Fibre; + + Fibre = DevPath; + CatPrint (Str, L"Fibre(%lx,%lx)", Fibre->WWN, Fibre->Lun); +} + +STATIC +VOID +DevPathToText1394 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + F1394_DEVICE_PATH *F1394; + + F1394 = DevPath; + CatPrint (Str, L"I1394(%lx)", F1394->Guid); +} + +STATIC +VOID +DevPathToTextUsb ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + USB_DEVICE_PATH *Usb; + + Usb = DevPath; + CatPrint (Str, L"USB(%x,%x)", Usb->ParentPortNumber, Usb->InterfaceNumber); +} + +STATIC +VOID +DevPathToTextUsbWWID ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + USB_WWID_DEVICE_PATH *UsbWWId; + + UsbWWId = DevPath; + CatPrint ( + Str, + L"UsbWwid(%x,%x,%x,\"WWID\")", + UsbWWId->VendorId, + UsbWWId->ProductId, + UsbWWId->InterfaceNumber + ); +} + +STATIC +VOID +DevPathToTextLogicalUnit ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit; + + LogicalUnit = DevPath; + CatPrint (Str, L"Unit(%x)", LogicalUnit->Lun); +} + +STATIC +VOID +DevPathToTextUsbClass ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + USB_CLASS_DEVICE_PATH *UsbClass; + + UsbClass = DevPath; + + if (AllowShortcuts == TRUE) { + switch (UsbClass->DeviceClass) { + case 1: + CatPrint ( + Str, + L"UsbAudio(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 2: + CatPrint ( + Str, + L"UsbCDCControl(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 3: + CatPrint ( + Str, + L"UsbHID(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 6: + CatPrint ( + Str, + L"UsbImage(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 7: + CatPrint ( + Str, + L"UsbPrinter(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 8: + CatPrint ( + Str, + L"UsbMassStorage(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 9: + CatPrint ( + Str, + L"UsbHub(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 10: + CatPrint ( + Str, + L"UsbCDCData(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 11: + CatPrint ( + Str, + L"UsbSmartCard(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 14: + CatPrint ( + Str, + L"UsbVideo(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 220: + CatPrint ( + Str, + L"UsbDiagnostic(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 224: + CatPrint ( + Str, + L"UsbWireless(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 254: + if (UsbClass->DeviceSubClass == 1) { + CatPrint ( + Str, + L"UsbDeviceFirmwareUpdate(%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceProtocol + ); + } else if (UsbClass->DeviceSubClass == 2) { + CatPrint ( + Str, + L"UsbIrdaBridge(%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceProtocol + ); + } else if (UsbClass->DeviceSubClass == 3) { + CatPrint ( + Str, + L"UsbTestAndMeasurement(%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceProtocol + ); + } + break; + + default: + break; + } + + return ; + } + + CatPrint ( + Str, + L"UsbClass(%x,%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceClass, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); +} + +STATIC +VOID +DevPathToTextI2O ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + I2O_DEVICE_PATH *I2O; + + I2O = DevPath; + CatPrint (Str, L"I2O(%x)", I2O->Tid); +} + +STATIC +VOID +DevPathToTextMacAddr ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + MAC_ADDR_DEVICE_PATH *MAC; + UINTN HwAddressSize; + UINTN Index; + + MAC = DevPath; + + HwAddressSize = sizeof (EFI_MAC_ADDRESS); + if (MAC->IfType == 0x01 || MAC->IfType == 0x00) { + HwAddressSize = 6; + } + + CatPrint (Str, L"MAC("); + + for (Index = 0; Index < HwAddressSize; Index++) { + CatPrint (Str, L"%02x", MAC->MacAddress.Addr[Index]); + } + + CatPrint (Str, L",%x)", MAC->IfType); +} + +STATIC +VOID +DevPathToTextIPv4 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + IPv4_DEVICE_PATH *IP; + + IP = DevPath; + if (DisplayOnly == TRUE) { + CatPrint ( + Str, + L"IPv4(%d.%d.%d.%d)", + IP->RemoteIpAddress.Addr[0], + IP->RemoteIpAddress.Addr[1], + IP->RemoteIpAddress.Addr[2], + IP->RemoteIpAddress.Addr[3] + ); + return ; + } + + CatPrint ( + Str, + L"IPv4(%d.%d.%d.%d,%s,%s,%d.%d.%d.%d)", + IP->RemoteIpAddress.Addr[0], + IP->RemoteIpAddress.Addr[1], + IP->RemoteIpAddress.Addr[2], + IP->RemoteIpAddress.Addr[3], + IP->Protocol ? L"TCP" : L"UDP", + (IP->StaticIpAddress == TRUE) ? L"Static" : L"DHCP", + IP->LocalIpAddress.Addr[0], + IP->LocalIpAddress.Addr[1], + IP->LocalIpAddress.Addr[2], + IP->LocalIpAddress.Addr[3] + ); +} + +STATIC +VOID +DevPathToTextIPv6 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + IPv6_DEVICE_PATH *IP; + + IP = DevPath; + if (DisplayOnly == TRUE) { + CatPrint ( + Str, + L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)", + IP->RemoteIpAddress.Addr[0], + IP->RemoteIpAddress.Addr[1], + IP->RemoteIpAddress.Addr[2], + IP->RemoteIpAddress.Addr[3], + IP->RemoteIpAddress.Addr[4], + IP->RemoteIpAddress.Addr[5], + IP->RemoteIpAddress.Addr[6], + IP->RemoteIpAddress.Addr[7], + IP->RemoteIpAddress.Addr[8], + IP->RemoteIpAddress.Addr[9], + IP->RemoteIpAddress.Addr[10], + IP->RemoteIpAddress.Addr[11], + IP->RemoteIpAddress.Addr[12], + IP->RemoteIpAddress.Addr[13], + IP->RemoteIpAddress.Addr[14], + IP->RemoteIpAddress.Addr[15] + ); + return ; + } + + CatPrint ( + Str, + L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x,%s,%s,%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)", + IP->RemoteIpAddress.Addr[0], + IP->RemoteIpAddress.Addr[1], + IP->RemoteIpAddress.Addr[2], + IP->RemoteIpAddress.Addr[3], + IP->RemoteIpAddress.Addr[4], + IP->RemoteIpAddress.Addr[5], + IP->RemoteIpAddress.Addr[6], + IP->RemoteIpAddress.Addr[7], + IP->RemoteIpAddress.Addr[8], + IP->RemoteIpAddress.Addr[9], + IP->RemoteIpAddress.Addr[10], + IP->RemoteIpAddress.Addr[11], + IP->RemoteIpAddress.Addr[12], + IP->RemoteIpAddress.Addr[13], + IP->RemoteIpAddress.Addr[14], + IP->RemoteIpAddress.Addr[15], + IP->Protocol ? L"TCP" : L"UDP", + (IP->StaticIpAddress == TRUE) ? L"Static" : L"DHCP", + IP->LocalIpAddress.Addr[0], + IP->LocalIpAddress.Addr[1], + IP->LocalIpAddress.Addr[2], + IP->LocalIpAddress.Addr[3], + IP->LocalIpAddress.Addr[4], + IP->LocalIpAddress.Addr[5], + IP->LocalIpAddress.Addr[6], + IP->LocalIpAddress.Addr[7], + IP->LocalIpAddress.Addr[8], + IP->LocalIpAddress.Addr[9], + IP->LocalIpAddress.Addr[10], + IP->LocalIpAddress.Addr[11], + IP->LocalIpAddress.Addr[12], + IP->LocalIpAddress.Addr[13], + IP->LocalIpAddress.Addr[14], + IP->LocalIpAddress.Addr[15] + ); +} + +STATIC +VOID +DevPathToTextInfiniBand ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + INFINIBAND_DEVICE_PATH *InfiniBand; + + InfiniBand = DevPath; + CatPrint ( + Str, + L"Infiniband(%x,%g,%lx,%lx,%lx)", + InfiniBand->ResourceFlags, + InfiniBand->PortGid, + InfiniBand->ServiceId, + InfiniBand->TargetPortId, + InfiniBand->DeviceId + ); +} + +STATIC +VOID +DevPathToTextUart ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + UART_DEVICE_PATH *Uart; + CHAR8 Parity; + + Uart = DevPath; + switch (Uart->Parity) { + case 0: + Parity = 'D'; + break; + + case 1: + Parity = 'N'; + break; + + case 2: + Parity = 'E'; + break; + + case 3: + Parity = 'O'; + break; + + case 4: + Parity = 'M'; + break; + + case 5: + Parity = 'S'; + break; + + default: + Parity = 'x'; + break; + } + + if (Uart->BaudRate == 0) { + CatPrint (Str, L"Uart(DEFAULT,"); + } else { + CatPrint (Str, L"Uart(%ld,", Uart->BaudRate); + } + + if (Uart->DataBits == 0) { + CatPrint (Str, L"DEFAULT,"); + } else { + CatPrint (Str, L"%d,", Uart->DataBits); + } + + CatPrint (Str, L"%c,", Parity); + + switch (Uart->StopBits) { + case 0: + CatPrint (Str, L"D)"); + break; + + case 1: + CatPrint (Str, L"1)"); + break; + + case 2: + CatPrint (Str, L"1.5)"); + break; + + case 3: + CatPrint (Str, L"2)"); + break; + + default: + CatPrint (Str, L"x)"); + break; + } +} + +STATIC +VOID +DevPathToTextiSCSI ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + ISCSI_DEVICE_PATH_WITH_NAME *iSCSI; + UINT16 Options; + + iSCSI = DevPath; + CatPrint ( + Str, + L"iSCSI(%s,%x,%lx,", + iSCSI->iSCSITargetName, + iSCSI->TargetPortalGroupTag, + iSCSI->Lun + ); + + Options = iSCSI->LoginOption; + CatPrint (Str, L"%s,", ((Options >> 1) & 0x0001) ? L"CRC32C" : L"None"); + CatPrint (Str, L"%s,", ((Options >> 3) & 0x0001) ? L"CRC32C" : L"None"); + if ((Options >> 11) & 0x0001) { + CatPrint (Str, L"%s,", L"None"); + } else if ((Options >> 12) & 0x0001) { + CatPrint (Str, L"%s,", L"CHAP_UNI"); + } else { + CatPrint (Str, L"%s,", L"CHAP_BI"); + + } + + CatPrint (Str, L"%s)", (iSCSI->NetworkProtocol == 0) ? L"TCP" : L"reserved"); +} + +STATIC +VOID +DevPathToTextHardDrive ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + HARDDRIVE_DEVICE_PATH *Hd; + + Hd = DevPath; + switch (Hd->SignatureType) { + case 0: + CatPrint ( + Str, + L"HD(%d,%s,0,", + Hd->PartitionNumber, + L"None" + ); + break; + + case SIGNATURE_TYPE_MBR: + CatPrint ( + Str, + L"HD(%d,%s,%08x,", + Hd->PartitionNumber, + L"MBR", + *((UINT32 *) (&(Hd->Signature[0]))) + ); + break; + + case SIGNATURE_TYPE_GUID: + CatPrint ( + Str, + L"HD(%d,%s,%g,", + Hd->PartitionNumber, + L"GUID", + (EFI_GUID *) &(Hd->Signature[0]) + ); + break; + + default: + break; + } + + CatPrint (Str, L"%lx,%lx)", Hd->PartitionStart, Hd->PartitionSize); +} + +STATIC +VOID +DevPathToTextCDROM ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + CDROM_DEVICE_PATH *Cd; + + Cd = DevPath; + if (DisplayOnly == TRUE) { + CatPrint (Str, L"CDROM(%x)", Cd->BootEntry); + return ; + } + + CatPrint (Str, L"CDROM(%x,%lx,%lx)", Cd->BootEntry, Cd->PartitionStart, Cd->PartitionSize); +} + +STATIC +VOID +DevPathToTextFilePath ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + FILEPATH_DEVICE_PATH *Fp; + + Fp = DevPath; + CatPrint (Str, L"%s", Fp->PathName); +} + +STATIC +VOID +DevPathToTextMediaProtocol ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + MEDIA_PROTOCOL_DEVICE_PATH *MediaProt; + + MediaProt = DevPath; + CatPrint (Str, L"Media(%g)", &MediaProt->Protocol); +} + +STATIC +VOID +DevPathToTextBBS ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + BBS_BBS_DEVICE_PATH *Bbs; + CHAR16 *Type; + + Bbs = DevPath; + switch (Bbs->DeviceType) { + case BBS_TYPE_FLOPPY: + Type = L"Floppy"; + break; + + case BBS_TYPE_HARDDRIVE: + Type = L"HD"; + break; + + case BBS_TYPE_CDROM: + Type = L"CDROM"; + break; + + case BBS_TYPE_PCMCIA: + Type = L"PCMCIA"; + break; + + case BBS_TYPE_USB: + Type = L"USB"; + break; + + case BBS_TYPE_EMBEDDED_NETWORK: + Type = L"Network"; + break; + + default: + Type = L"?"; + break; + } + + CatPrint (Str, L"BBS(%s,%a", Type, Bbs->String); + + if (DisplayOnly == TRUE) { + CatPrint (Str, L")"); + return ; + } + + CatPrint (Str, L",%x)", Bbs->StatusFlag); +} + +STATIC +VOID +DevPathToTextEndInstance ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + CatPrint (Str, L","); +} + +STATIC +VOID +DevPathToTextNodeUnknown ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + CatPrint (Str, L"?"); +} + +GLOBAL_REMOVE_IF_UNREFERENCED const DEVICE_PATH_TO_TEXT_TABLE DevPathToTextTable[] = { + {HARDWARE_DEVICE_PATH, HW_PCI_DP, DevPathToTextPci}, + {HARDWARE_DEVICE_PATH, HW_PCCARD_DP, DevPathToTextPccard}, + {HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, DevPathToTextMemMap}, + {HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DevPathToTextVendor}, + {HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, DevPathToTextController}, + {ACPI_DEVICE_PATH, ACPI_DP, DevPathToTextAcpi}, + {ACPI_DEVICE_PATH, ACPI_EXTENDED_DP, DevPathToTextExtAcpi}, + {MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, DevPathToTextAtapi}, + {MESSAGING_DEVICE_PATH, MSG_SCSI_DP, DevPathToTextScsi}, + {MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, DevPathToTextFibre}, + {MESSAGING_DEVICE_PATH, MSG_1394_DP, DevPathToText1394}, + {MESSAGING_DEVICE_PATH, MSG_USB_DP, DevPathToTextUsb}, + {MESSAGING_DEVICE_PATH, MSG_USB_WWID_DP, DevPathToTextUsbWWID}, + {MESSAGING_DEVICE_PATH, MSG_DEVICE_LOGICAL_UNIT_DP, DevPathToTextLogicalUnit}, + {MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP, DevPathToTextUsbClass}, + {MESSAGING_DEVICE_PATH, MSG_I2O_DP, DevPathToTextI2O}, + {MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, DevPathToTextMacAddr}, + {MESSAGING_DEVICE_PATH, MSG_IPv4_DP, DevPathToTextIPv4}, + {MESSAGING_DEVICE_PATH, MSG_IPv6_DP, DevPathToTextIPv6}, + {MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, DevPathToTextInfiniBand}, + {MESSAGING_DEVICE_PATH, MSG_UART_DP, DevPathToTextUart}, + {MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, DevPathToTextVendor}, + {MESSAGING_DEVICE_PATH, MSG_ISCSI_DP, DevPathToTextiSCSI}, + {MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, DevPathToTextHardDrive}, + {MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, DevPathToTextCDROM}, + {MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, DevPathToTextVendor}, + {MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, DevPathToTextFilePath}, + {MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, DevPathToTextMediaProtocol}, + {MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, DevPathToTextFilePath}, + {BBS_DEVICE_PATH, BBS_BBS_DP, DevPathToTextBBS}, + {END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, DevPathToTextEndInstance}, + {0, 0, NULL} +}; + +CHAR16 * +ConvertDeviceNodeToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +/*++ + + Routine Description: + Convert a device node to its text representation. + + Arguments: + DeviceNode - Points to the device node to be converted. + DisplayOnly - If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + AllowShortcuts - If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + Returns: + A pointer - a pointer to the allocated text representation of the device node. + NULL - if DeviceNode is NULL or there was insufficient memory. + +--*/ +{ + POOL_PRINT Str; + UINTN Index; + UINTN NewSize; + VOID (*DumpNode)(POOL_PRINT *, VOID *, BOOLEAN, BOOLEAN); + + if (DeviceNode == NULL) { + return NULL; + } + + ZeroMem (&Str, sizeof (Str)); + + // + // Process the device path node + // + DumpNode = NULL; + for (Index = 0; DevPathToTextTable[Index].Function != NULL; Index++) { + if (DevicePathType (DeviceNode) == DevPathToTextTable[Index].Type && + DevicePathSubType (DeviceNode) == DevPathToTextTable[Index].SubType + ) { + DumpNode = DevPathToTextTable[Index].Function; + break; + } + } + // + // If not found, use a generic function + // + if (DumpNode == NULL) { + DumpNode = DevPathToTextNodeUnknown; + } + + // + // Print this node + // + DumpNode (&Str, (VOID *) DeviceNode, DisplayOnly, AllowShortcuts); + + // + // Shrink pool used for string allocation + // + NewSize = (Str.Len + 1) * sizeof (CHAR16); + Str.Str = ReallocatePool (Str.Str, NewSize, NewSize); + ASSERT (Str.Str != NULL); + Str.Str[Str.Len] = 0; + return Str.Str; +} + +CHAR16 * +ConvertDevicePathToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +/*++ + + Routine Description: + Convert a device path to its text representation. + + Arguments: + DeviceNode - Points to the device path to be converted. + DisplayOnly - If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + AllowShortcuts - If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + Returns: + A pointer - a pointer to the allocated text representation of the device path. + NULL - if DeviceNode is NULL or there was insufficient memory. + +--*/ +{ + POOL_PRINT Str; + EFI_DEVICE_PATH_PROTOCOL *DevPathNode; + EFI_DEVICE_PATH_PROTOCOL *UnpackDevPath; + UINTN Index; + UINTN NewSize; + VOID (*DumpNode) (POOL_PRINT *, VOID *, BOOLEAN, BOOLEAN); + + if (DevicePath == NULL) { + return NULL; + } + + ZeroMem (&Str, sizeof (Str)); + + // + // Unpacked the device path + // + UnpackDevPath = UnpackDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath); + ASSERT (UnpackDevPath != NULL); + + // + // Process each device path node + // + DevPathNode = UnpackDevPath; + while (!IsDevicePathEnd (DevPathNode)) { + // + // Find the handler to dump this device path node + // + DumpNode = NULL; + for (Index = 0; DevPathToTextTable[Index].Function; Index += 1) { + + if (DevicePathType (DevPathNode) == DevPathToTextTable[Index].Type && + DevicePathSubType (DevPathNode) == DevPathToTextTable[Index].SubType + ) { + DumpNode = DevPathToTextTable[Index].Function; + break; + } + } + // + // If not found, use a generic function + // + if (!DumpNode) { + DumpNode = DevPathToTextNodeUnknown; + } + // + // Put a path seperator in if needed + // + if (Str.Len && DumpNode != DevPathToTextEndInstance) { + if (*(Str.Str + Str.Len / sizeof (CHAR16) - 1) != L',') { + CatPrint (&Str, L"/"); + } + } + // + // Print this node of the device path + // + DumpNode (&Str, DevPathNode, DisplayOnly, AllowShortcuts); + + // + // Next device path node + // + DevPathNode = NextDevicePathNode (DevPathNode); + } + // + // Shrink pool used for string allocation + // + FreePool (UnpackDevPath); + + NewSize = (Str.Len + 1) * sizeof (CHAR16); + Str.Str = ReallocatePool (Str.Str, NewSize, NewSize); + ASSERT (Str.Str != NULL); + Str.Str[Str.Len] = 0; + return Str.Str; +} diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePathUtilities.c b/MdeModulePkg/Universal/DevicePathDxe/DevicePathUtilities.c new file mode 100644 index 0000000000..a78a24d9f5 --- /dev/null +++ b/MdeModulePkg/Universal/DevicePathDxe/DevicePathUtilities.c @@ -0,0 +1,216 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DevicePathUtilities.c + +Abstract: + + Implementation file for Device Path Utilities Protocol + +--*/ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +#include "DevicePath.h" + +UINTN +GetDevicePathSizeProtocolInterface ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + + Routine Description: + Returns the size of the device path, in bytes. + + Arguments: + DevicePath - Points to the start of the EFI device path. + + Returns: + Size - Size of the specified device path, in bytes, including the end-of-path tag. + +--*/ +{ + return GetDevicePathSize (DevicePath); +} + +EFI_DEVICE_PATH_PROTOCOL * +DuplicateDevicePathProtocolInterface ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + + Routine Description: + Create a duplicate of the specified path. + + Arguments: + DevicePath - Points to the source EFI device path. + + Returns: + Pointer - A pointer to the duplicate device path. + NULL - Insufficient memory. + +--*/ +{ + return DuplicateDevicePath (DevicePath); +} + +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePathProtocolInterface ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *Src1, + IN CONST EFI_DEVICE_PATH_PROTOCOL *Src2 + ) +/*++ + + Routine Description: + Create a new path by appending the second device path to the first. + + Arguments: + Src1 - Points to the first device path. If NULL, then it is ignored. + Src2 - Points to the second device path. If NULL, then it is ignored. + + Returns: + Pointer - A pointer to the newly created device path. + NULL - Memory could not be allocated + or either DevicePath or DeviceNode is NULL. + +--*/ +{ + return AppendDevicePath (Src1, Src2); +} + +EFI_DEVICE_PATH_PROTOCOL * +AppendDeviceNodeProtocolInterface ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode + ) +/*++ + + Routine Description: + Creates a new path by appending the device node to the device path. + + Arguments: + DevicePath - Points to the device path. + DeviceNode - Points to the device node. + + Returns: + Pointer - A pointer to the allocated device node. + NULL - Memory could not be allocated + or either DevicePath or DeviceNode is NULL. + +--*/ +{ + return AppendDevicePathNode (DevicePath, DeviceNode); +} + +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePathInstanceProtocolInterface ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance + ) +/*++ + + Routine Description: + Creates a new path by appending the specified device path instance to the specified device path. + + Arguments: + DevicePath - Points to the device path. If NULL, then ignored. + DevicePathInstance - Points to the device path instance. + + Returns: + Pointer - A pointer to the newly created device path + NULL - Memory could not be allocated or DevicePathInstance is NULL. + +--*/ +{ + return AppendDevicePathInstance (DevicePath, DevicePathInstance); +} + +EFI_DEVICE_PATH_PROTOCOL * +GetNextDevicePathInstanceProtocolInterface ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathInstance, + OUT UINTN *DevicePathInstanceSize + ) +/*++ + + Routine Description: + Creates a copy of the current device path instance and returns a pointer to the next device path instance. + + Arguments: + DevicePathInstance - On input, this holds the pointer to the current device path + instance. On output, this holds the pointer to the next + device path instance or NULL if there are no more device + path instances in the device path. + DevicePathInstanceSize - On output, this holds the size of the device path instance, + in bytes or zero, if DevicePathInstance is zero. + + Returns: + Pointer - A pointer to the copy of the current device path instance. + NULL - DevicePathInstace was NULL on entry or there was insufficient memory. + +--*/ +{ + return GetNextDevicePathInstance (DevicePathInstance, DevicePathInstanceSize); +} + +BOOLEAN +IsDevicePathMultiInstanceProtocolInterface ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + + Routine Description: + Returns whether a device path is multi-instance. + + Arguments: + DevicePath - Points to the device path. If NULL, then ignored. + + Returns: + TRUE - The device path has more than one instance + FALSE - The device path is empty or contains only a single instance. + +--*/ +{ + return IsDevicePathMultiInstance (DevicePath); +} + +EFI_DEVICE_PATH_PROTOCOL * +CreateDeviceNodeProtocolInterface ( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength + ) +/*++ + + Routine Description: + Creates a device node + + Arguments: + NodeType - NodeType is the device node type (EFI_DEVICE_PATH.Type) for + the new device node. + NodeSubType - NodeSubType is the device node sub-type + EFI_DEVICE_PATH.SubType) for the new device node. + NodeLength - NodeLength is the length of the device node + (EFI_DEVICE_PATH.Length) for the new device node. + + Returns: + Pointer - A pointer to the newly created device node. + NULL - NodeLength is less than + the size of the header or there was insufficient memory. + +--*/ +{ + return CreateDeviceNode (NodeType, NodeSubType, NodeLength); +} diff --git a/Nt32Pkg/Library/Nt32PeCoffLoaderLib/CommonHeader.h b/Nt32Pkg/Library/Nt32PeCoffLoaderLib/CommonHeader.h index 28a2f5d8bc..98046089bf 100644 --- a/Nt32Pkg/Library/Nt32PeCoffLoaderLib/CommonHeader.h +++ b/Nt32Pkg/Library/Nt32PeCoffLoaderLib/CommonHeader.h @@ -19,8 +19,7 @@ // // The package level header files this module uses // -#include -#include +#include // // The protocols, PPI and GUID defintions for this module // @@ -28,6 +27,6 @@ // // The Library classes this module consumes // -#include +#include #endif diff --git a/Nt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.inf b/Nt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.inf index 8141c1450d..a24b544d23 100644 --- a/Nt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.inf +++ b/Nt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.inf @@ -56,6 +56,7 @@ [Packages] MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec ################################################################################ diff --git a/Nt32Pkg/Nt32Pkg.dec b/Nt32Pkg/Nt32Pkg.dec index 5cd2b2e50e..8982318cc4 100644 --- a/Nt32Pkg/Nt32Pkg.dec +++ b/Nt32Pkg/Nt32Pkg.dec @@ -70,6 +70,8 @@ gEfiWinNtPhysicalDisksGuid = { 0x0C95A92F, 0xA006, 0x11D4, { 0xBC, 0xFA, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }} gEfiWinNtVirtualDisksGuid = { 0x0C95A928, 0xA006, 0x11D4, { 0xBC, 0xFA, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }} gEfiNt32PkgTokenSpaceGuid = { 0x0D79A645, 0x1D91, 0x40a6, { 0xA8, 0x1F, 0x61, 0xE6, 0x98, 0x2B, 0x32, 0xB4 }} + gEfiEndOfPeiSignalPpiGuid = { 0x605EA650, 0xC65C, 0x42e1, { 0xBA, 0x80, 0x91, 0xA5, 0x2A, 0xB6, 0x18, 0xC6 }} + gEfiPeiFvFileLoaderPpiGuid = { 0x7e1f0d85, 0x04ff, 0x4bb2, { 0x86, 0x6a, 0x31, 0xa2, 0x99, 0x6a, 0x48, 0xa8 }} ################################################################################ diff --git a/Nt32Pkg/Nt32Pkg.dsc b/Nt32Pkg/Nt32Pkg.dsc index e6ebbe1045..527fffce19 100644 --- a/Nt32Pkg/Nt32Pkg.dsc +++ b/Nt32Pkg/Nt32Pkg.dsc @@ -63,12 +63,10 @@ [LibraryClasses.common] TimerLib|$(WORKSPACE)/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf PrintLib|$(WORKSPACE)/MdePkg/Library/BasePrintLib/BasePrintLib.inf - UefiDecompressLib|$(WORKSPACE)/MdeModulePkg/Library/BaseUefiTianoDecompressLib/BaseUefiTianoDecompressLib.inf DebugLib|$(WORKSPACE)/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf SerialPortLib|$(WORKSPACE)/MdePkg/Library/SerialPortLibNull/SerialPortLibNull.inf BaseMemoryLib|$(WORKSPACE)/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf BaseLib|$(WORKSPACE)/MdePkg/Library/BaseLib/BaseLib.inf - CustomDecompressLib|$(WORKSPACE)/MdeModulePkg/Library/BaseCustomDecompressLibNull/BaseCustomDecompressLibNull.inf PerformanceLib|$(WORKSPACE)/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf PeCoffLib|$(WORKSPACE)/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf PciIncompatibleDeviceSupportLib|${WORKSPACE}/IntelFrameworkModulePkg/Library/PciIncompatibleDeviceSupportLib/PciIncompatibleDeviceSupportLib.inf @@ -77,6 +75,8 @@ GraphicsLib|$(WORKSPACE)/IntelFrameworkModulePkg/Library/GraphicsLib/GraphicsLib.inf FvbServiceLib|${WORKSPACE}/MdeModulePkg/Library/EdkFvbServiceLib/EdkFvbServiceLib.inf IoLib|$(WORKSPACE)/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + CustomDecompressLib|${WORKSPACE}/IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + HiiLib|${WORKSPACE}/IntelFrameworkPkg/Library/HiiLibFramework/HiiLib.inf [LibraryClasses.common.DXE_CORE] DevicePathLib|$(WORKSPACE)/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf @@ -215,6 +215,15 @@ # ################################################################################ +[PcdsFeatureFlag.common] + PcdDevicePathSupportDevicePathFromText|gEfiEdkModulePkgTokenSpaceGuid|FALSE + PcdDevicePathSupportDevicePathToText|gEfiEdkModulePkgTokenSpaceGuid|FALSE + PcdDxeIplSupportCustomDecompress|gEfiEdkModulePkgTokenSpaceGuid|TRUE + PcdDxeIplBuildShareCodeHobs|gEfiEdkModulePkgTokenSpaceGuid|FALSE + PcdDxeIplSupportEfiDecompress|gEfiEdkModulePkgTokenSpaceGuid|TRUE + PcdDxeIplSupportTianoDecompress|gEfiEdkModulePkgTokenSpaceGuid|TRUE + PcdDxeIplSupportCustomDecompress|gEfiEdkModulePkgTokenSpaceGuid|TRUE + [PcdsPatchableInModule.IA32] PcdStatusCodeMemorySize|gEfiIntelFrameworkModulePkgTokenSpaceGuid|1 PcdStatusCodeRuntimeMemorySize|gEfiIntelFrameworkModulePkgTokenSpaceGuid|128 @@ -369,4 +378,9 @@ $(WORKSPACE)/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.inf ##This driver follows UEFI specification definition $(WORKSPACE)/Nt32Pkg/Sec/SecMain.inf $(WORKSPACE)/MdeModulePkg/Core/Pei/PeiMain.inf - \ No newline at end of file + ${WORKSPACE}/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.inf + ${WORKSPACE}/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.inf + ${WORKSPACE}/MdeModulePkg/Universal/DevicePathDxe/DevicePath.inf + ${WORKSPACE}/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.inf + ${WORKSPACE}/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf + ${WORKSPACE}/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.inf \ No newline at end of file -- 2.30.2