From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4001:c06::232; helo=mail-io0-x232.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-io0-x232.google.com (mail-io0-x232.google.com [IPv6:2607:f8b0:4001:c06::232]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id B42BC222630DC for ; Thu, 22 Feb 2018 09:44:37 -0800 (PST) Received: by mail-io0-x232.google.com with SMTP id p78so6854110iod.13 for ; Thu, 22 Feb 2018 09:50:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=bn3b2gji/2ZeoSXNYdPj2EtPG6pWu5aIat+/bsoEnnA=; b=SSz/WxYvgX16+9VMFqlYx6X/hB0p0U2NkYcOnR/KwQjr1hlLfGuR5If5c1GlE3JX+B 2Rjru+G2hbPMDymJT8DSlWHWQjFCDwSzHPteUkXmdsMhUTqHaAIqaMfDYBSGrKb7U5c2 JPY/Zflfv3TanltQUgYtJaYcPP46dQDMzOULs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=bn3b2gji/2ZeoSXNYdPj2EtPG6pWu5aIat+/bsoEnnA=; b=tBos0jvwvl9tOGlNJy/HcJe3NR70xKAvqGGLLe7C5ZC94Xs2PxQZqt6rmfLWnXgUCY ZylXbHRsYYYnKqT0If9enNdiWkV/IkhGcSg/KseKIjEgY7Qv8n0JL0rRwPqhEfwOv0xf +SlKJEcNaNRM8EZ3hRknuuNBdN5UQI7C6Pgewf/pGN7j2yJrSXjXWhZtWuGn4WK0UsC1 cS1ab1ry+u/nm3YtlhQiO8sz8M6AenP87CYmlWukTkuvYgygtaV/GMYiVLjAtJ+eFRg0 AiGVkaL5TU1ZgpduyyDqBODhfVhZtVSrdg/xRuE4DAZrr4N7V0iItZS0qoNC9kXFYUj2 e+wA== X-Gm-Message-State: APf1xPAXSpB+NoeOujIxlG4XjPg50kkfXnySbLAX1AMcq9/cS/iXexml wBFIAGTuGFPma4cAjoaP8QeUq8VuSx3A+mqZaBLvrQ== X-Google-Smtp-Source: AG47ELs5lJNFtOn4hPrkrz/+eOLzG3EGUM7G5qdxqQM3GmYgWH51X48Drs+QRO4oUZWrGIz28Snctv9BRqVGvHyBouk= X-Received: by 10.107.151.74 with SMTP id z71mr9222979iod.277.1519321837543; Thu, 22 Feb 2018 09:50:37 -0800 (PST) MIME-Version: 1.0 Received: by 10.107.138.209 with HTTP; Thu, 22 Feb 2018 09:50:36 -0800 (PST) In-Reply-To: References: <20180222162822.22703-1-ard.biesheuvel@linaro.org> <20180222162822.22703-2-ard.biesheuvel@linaro.org> From: Ard Biesheuvel Date: Thu, 22 Feb 2018 17:50:36 +0000 Message-ID: To: "Kinney, Michael D" Cc: "edk2-devel@lists.01.org" , "leif.lindholm@linaro.org" , "lersek@redhat.com" , "Gao, Liming" , "afish@apple.com" , "Zeng, Star" , "Ni, Ruiyu" Subject: Re: [PATCH edk2-platforms v2 1/2] MdePkg: introduce DxeRuntimeDebugLibSerialPort X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Feb 2018 17:44:38 -0000 Content-Type: text/plain; charset="UTF-8" On 22 February 2018 at 17:46, Kinney, Michael D wrote: > Ard, > > The check for the runtime flag seems inconsistent. > > Since the issue being addressed is use of SerialPortLib, > can't the mEfiAtRuntime flag be use around SerialPortLib > calls only. > I take it you mean the checks around ASSERT()s? I agree that those are redundant, since the check will occur in the ASSERT() implementation as well. Will fix. >> -----Original Message----- >> From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org] >> Sent: Thursday, February 22, 2018 8:28 AM >> To: edk2-devel@lists.01.org >> Cc: leif.lindholm@linaro.org; lersek@redhat.com; Gao, >> Liming ; Kinney, Michael D >> ; afish@apple.com; Zeng, >> Star ; Ni, Ruiyu >> ; Ard Biesheuvel >> >> Subject: [PATCH edk2-platforms v2 1/2] MdePkg: introduce >> DxeRuntimeDebugLibSerialPort >> >> Introduce a variant of BaseDebugLibSerialPort that >> behaves correctly with >> regards to the use of the serial port after >> ExitBootServices(). Also, it >> caches PCD values in the constructor so that no calls >> into PcdLib are >> made at runtime. >> >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Signed-off-by: Ard Biesheuvel >> >> --- >> MdePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c >> | 373 ++++++++++++++++++++ >> >> MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDe >> bugLibSerialPort.inf | 56 +++ >> >> MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDe >> bugLibSerialPort.uni | 21 ++ >> 3 files changed, 450 insertions(+) >> >> diff --git >> a/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c >> b/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c >> new file mode 100644 >> index 000000000000..8579469029a1 >> --- /dev/null >> +++ >> b/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c >> @@ -0,0 +1,373 @@ >> +/** @file >> + DXE runtime Debug library instance based on Serial >> Port library. >> + It takes care not to call into SerialPortLib or >> PcdLib after >> + ExitBootServices() has been called, to prevent >> touching hardware that is >> + no longer owned by the firmware, or invoking >> protocols that are not safe >> + for runtime (such as gEfiPcdProtocolGuid) >> + >> + Copyright (c) 2006 - 2011, Intel Corporation. All >> rights reserved.
>> + Copyright (c) 2018, Linaro, Ltd. 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 >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +STATIC EFI_EVENT mEfiExitBootServicesEvent; >> +STATIC BOOLEAN mEfiAtRuntime; >> + >> +STATIC UINT8 mDebugClearMemoryValue; >> +STATIC UINT8 mDebugPropertyMask; >> +STATIC UINT32 mFixedDebugPrintErrorLevel; >> + >> +// >> +// Define the maximum debug and assert message length >> that this library supports >> +// >> +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 >> + >> +/** >> + Set AtRuntime flag as TRUE after ExitBootServices. >> + >> + @param[in] Event The Event that is being >> processed. >> + @param[in] Context The Event Context. >> + >> +**/ >> +STATIC >> +VOID >> +EFIAPI >> +ExitBootServicesEvent ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ) >> +{ >> + mEfiAtRuntime = TRUE; >> +} >> + >> +/** >> + The constructor function to initialize the Serial >> Port library and >> + register a callback for the ExitBootServices event. >> + >> + @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 operation completed >> successfully. >> + @retval other Either the serial port failed >> to initialize or the >> + ExitBootServices event callback >> registration failed. >> +**/ >> +EFI_STATUS >> +EFIAPI >> +DxeRuntimeDebugLibSerialPortConstructor ( >> + IN EFI_HANDLE ImageHandle, >> + IN EFI_SYSTEM_TABLE *SystemTable >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + mDebugClearMemoryValue = PcdGet8 >> (PcdDebugClearMemoryValue); >> + mDebugPropertyMask = PcdGet8 >> (PcdDebugPropertyMask); >> + mFixedDebugPrintErrorLevel = PcdGet32 >> (PcdFixedDebugPrintErrorLevel); >> + >> + Status = SerialPortInitialize (); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + return SystemTable->BootServices->CreateEventEx >> (EVT_NOTIFY_SIGNAL, >> + TPL_NOTIFY, >> ExitBootServicesEvent, NULL, >> + >> &gEfiEventExitBootServicesGuid, >> + >> &mEfiExitBootServicesEvent); >> +} >> + >> +/** >> + If a runtime driver exits with an error, it must call >> this routine >> + to free the allocated resource before the exiting. >> + >> + @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 Runtime Driver Lib >> shutdown successfully. >> + @retval EFI_UNSUPPORTED Runtime Driver lib was >> not initialized. >> +**/ >> +EFI_STATUS >> +EFIAPI >> +DxeRuntimeDebugLibSerialPortDestructor ( >> + IN EFI_HANDLE ImageHandle, >> + IN EFI_SYSTEM_TABLE *SystemTable >> + ) >> +{ >> + return SystemTable->BootServices->CloseEvent >> (mEfiExitBootServicesEvent); >> +} >> + >> +/** >> + Prints a debug message to the debug output device if >> the specified error level >> + is enabled. >> + >> + If any bit in ErrorLevel is also set in >> DebugPrintErrorLevelLib function >> + GetDebugPrintErrorLevel (), then print the message >> specified by Format and the >> + associated variable argument list to the debug output >> device. >> + >> + If Format is NULL, then ASSERT(). >> + >> + @param ErrorLevel The error level of the debug >> message. >> + @param Format Format string for the debug >> message to print. >> + @param ... Variable argument list whose >> contents are accessed >> + based on the format string >> specified by Format. >> + >> +**/ >> +VOID >> +EFIAPI >> +DebugPrint ( >> + IN UINTN ErrorLevel, >> + IN CONST CHAR8 *Format, >> + ... >> + ) >> +{ >> + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; >> + VA_LIST Marker; >> + >> + if (mEfiAtRuntime) { >> + return; >> + } >> + >> + ASSERT (Format != NULL); >> + >> + // >> + // Check driver debug mask value and global mask >> + // >> + if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) { >> + return; >> + } >> + >> + // >> + // Convert the DEBUG() message to an ASCII String >> + // >> + VA_START (Marker, Format); >> + AsciiVSPrint (Buffer, sizeof (Buffer), Format, >> Marker); >> + VA_END (Marker); >> + >> + // >> + // Send the print string to a Serial Port >> + // >> + SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen >> (Buffer)); >> +} >> + >> + >> +/** >> + Prints an assert message containing a filename, line >> number, and description. >> + This may be followed by a breakpoint or a dead loop. >> + >> + Print a message of the form "ASSERT >> (): \n" >> + to the debug output device. If >> DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit >> + of PcdDebugProperyMask is set then CpuBreakpoint() is >> called. Otherwise, if >> + DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of >> PcdDebugProperyMask is set then >> + CpuDeadLoop() is called. If neither of these bits >> are set, then this function >> + returns immediately after the message is printed to >> the debug output device. >> + DebugAssert() must actively prevent recursion. If >> DebugAssert() is called >> + while processing another DebugAssert(), then >> DebugAssert() must return >> + immediately. >> + >> + If FileName is NULL, then a string of >> "(NULL) Filename" is printed. >> + If Description is NULL, then a string >> of "(NULL) Description" is >> + printed. >> + >> + @param FileName The pointer to the name of the >> source file that generated >> + the assert condition. >> + @param LineNumber The line number in the source >> file that generated the >> + assert condition >> + @param Description The pointer to the description >> of the assert condition. >> + >> +**/ >> +VOID >> +EFIAPI >> +DebugAssert ( >> + IN CONST CHAR8 *FileName, >> + IN UINTN LineNumber, >> + IN CONST CHAR8 *Description >> + ) >> +{ >> + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; >> + >> + if (!mEfiAtRuntime) { >> + // >> + // Generate the ASSERT() message in Ascii format >> + // >> + AsciiSPrint (Buffer, sizeof (Buffer), "ASSERT [%a] >> %a(%d): %a\n", >> + gEfiCallerBaseName, FileName, LineNumber, >> Description); >> + >> + // >> + // Send the print string to the Console Output >> device >> + // >> + SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen >> (Buffer)); >> + } >> + >> + // >> + // Generate a Breakpoint, DeadLoop, or NOP based on >> PCD settings >> + // >> + if ((mDebugPropertyMask & >> DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { >> + CpuBreakpoint (); >> + } else if ((mDebugPropertyMask & >> + DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) >> != 0) { >> + CpuDeadLoop (); >> + } >> +} >> + >> + >> +/** >> + Fills a target buffer with PcdDebugClearMemoryValue, >> and returns the target >> + buffer. >> + >> + This function fills Length bytes of Buffer with the >> value specified by >> + PcdDebugClearMemoryValue, and returns Buffer. >> + >> + If Buffer is NULL, then ASSERT(). >> + If Length is greater than (MAX_ADDRESS - Buffer + 1), >> then ASSERT(). >> + >> + @param Buffer The pointer to the target buffer to >> be filled with >> + PcdDebugClearMemoryValue. >> + @param Length The number of bytes in Buffer to >> fill with >> + PcdDebugClearMemoryValue. >> + >> + @return Buffer The pointer to the target buffer >> filled with >> + PcdDebugClearMemoryValue. >> + >> +**/ >> +VOID * >> +EFIAPI >> +DebugClearMemory ( >> + OUT VOID *Buffer, >> + IN UINTN Length >> + ) >> +{ >> + if (!mEfiAtRuntime) { >> + ASSERT (Buffer != NULL); >> + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + >> 1)); >> + } >> + >> + return SetMem (Buffer, Length, >> mDebugClearMemoryValue); >> +} >> + >> + >> +/** >> + Returns TRUE if ASSERT() macros are enabled. >> + >> + This function returns TRUE if the >> DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of >> + PcdDebugProperyMask is set. Otherwise FALSE is >> returned. >> + >> + @retval TRUE The >> DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of >> + PcdDebugProperyMask is set. >> + @retval FALSE The >> DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of >> + PcdDebugProperyMask is clear. >> + >> +**/ >> +BOOLEAN >> +EFIAPI >> +DebugAssertEnabled ( >> + VOID >> + ) >> +{ >> + return (BOOLEAN)((mDebugPropertyMask & >> + >> DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); >> +} >> + >> + >> +/** >> + Returns TRUE if DEBUG() macros are enabled. >> + >> + This function returns TRUE if the >> DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of >> + PcdDebugProperyMask is set. Otherwise FALSE is >> returned. >> + >> + @retval TRUE The >> DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of >> + PcdDebugProperyMask is set. >> + @retval FALSE The >> DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of >> + PcdDebugProperyMask is clear. >> + >> +**/ >> +BOOLEAN >> +EFIAPI >> +DebugPrintEnabled ( >> + VOID >> + ) >> +{ >> + return (BOOLEAN)((mDebugPropertyMask & >> + DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) >> != 0); >> +} >> + >> + >> +/** >> + Returns TRUE if DEBUG_CODE() macros are enabled. >> + >> + This function returns TRUE if the >> DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of >> + PcdDebugProperyMask is set. Otherwise FALSE is >> returned. >> + >> + @retval TRUE The >> DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of >> + PcdDebugProperyMask is set. >> + @retval FALSE The >> DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of >> + PcdDebugProperyMask is clear. >> + >> +**/ >> +BOOLEAN >> +EFIAPI >> +DebugCodeEnabled ( >> + VOID >> + ) >> +{ >> + return (BOOLEAN)((mDebugPropertyMask & >> + DEBUG_PROPERTY_DEBUG_CODE_ENABLED) >> != 0); >> +} >> + >> + >> +/** >> + Returns TRUE if DEBUG_CLEAR_MEMORY() macro is >> enabled. >> + >> + This function returns TRUE if the >> DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of >> + PcdDebugProperyMask is set. Otherwise FALSE is >> returned. >> + >> + @retval TRUE The >> DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of >> + PcdDebugProperyMask is set. >> + @retval FALSE The >> DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of >> + PcdDebugProperyMask is clear. >> + >> +**/ >> +BOOLEAN >> +EFIAPI >> +DebugClearMemoryEnabled ( >> + VOID >> + ) >> +{ >> + return (BOOLEAN)((mDebugPropertyMask & >> + >> DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); >> +} >> + >> +/** >> + Returns TRUE if any one of the bit is set both in >> ErrorLevel and >> + PcdFixedDebugPrintErrorLevel. >> + >> + This function compares the bit mask of ErrorLevel and >> + PcdFixedDebugPrintErrorLevel. >> + >> + @retval TRUE Current ErrorLevel is supported. >> + @retval FALSE Current ErrorLevel is not supported. >> + >> +**/ >> +BOOLEAN >> +EFIAPI >> +DebugPrintLevelEnabled ( >> + IN CONST UINTN ErrorLevel >> + ) >> +{ >> + return (BOOLEAN)((ErrorLevel & >> mFixedDebugPrintErrorLevel) != 0); >> +} >> diff --git >> a/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntime >> DebugLibSerialPort.inf >> b/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntime >> DebugLibSerialPort.inf >> new file mode 100644 >> index 000000000000..d5e9d3f8dee7 >> --- /dev/null >> +++ >> b/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntime >> DebugLibSerialPort.inf >> @@ -0,0 +1,56 @@ >> +## @file >> +# DXE runtime Debug library instance based on Serial >> Port library. >> +# It takes care not to call into SerialPortLib or >> PcdLib after >> +# ExitBootServices() has been called, to prevent >> touching hardware that is >> +# no longer owned by the firmware, or invoking >> protocols that are not safe >> +# for runtime (such as gEfiPcdProtocolGuid) >> +# >> +# Copyright (c) 2006 - 2015, Intel Corporation. All >> rights reserved.
>> +# Copyright (c) 2018, Linaro, Ltd. 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] >> + INF_VERSION = 0x0001001A >> + BASE_NAME = >> DxeRuntimeDebugLibSerialPort >> + MODULE_UNI_FILE = >> DxeRuntimeDebugLibSerialPort.uni >> + FILE_GUID = 9D914E2F-7CCB-41DB- >> 8E74-9AFF8F3BBFBF >> + MODULE_TYPE = DXE_RUNTIME_DRIVER >> + VERSION_STRING = 1.0 >> + LIBRARY_CLASS = >> DebugLib|DXE_RUNTIME_DRIVER >> + CONSTRUCTOR = >> DxeRuntimeDebugLibSerialPortConstructor >> + DESTRUCTOR = >> DxeRuntimeDebugLibSerialPortDestructor >> + >> +# >> +# VALID_ARCHITECTURES = AARCH64 ARM IA32 X64 >> IPF EBC >> +# >> + >> +[Sources] >> + DebugLib.c >> + >> +[Packages] >> + MdePkg/MdePkg.dec >> + >> +[LibraryClasses] >> + BaseLib >> + BaseMemoryLib >> + DebugPrintErrorLevelLib >> + PcdLib >> + PrintLib >> + SerialPortLib >> + >> +[Guids] >> + gEfiEventExitBootServicesGuid >> ## CONSUMES ## Event >> + >> +[Pcd] >> + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue >> ## CONSUMES >> + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask >> ## CONSUMES >> + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel >> ## CONSUMES >> diff --git >> a/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntime >> DebugLibSerialPort.uni >> b/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntime >> DebugLibSerialPort.uni >> new file mode 100644 >> index 000000000000..cd65515c4177 >> --- /dev/null >> +++ >> b/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntime >> DebugLibSerialPort.uni >> @@ -0,0 +1,21 @@ >> +// /** @file >> +// Instance of Debug Library based on Serial Port >> Library. >> +// >> +// It uses Print Library to produce formatted output >> strings to seiral port device. >> +// >> +// Copyright (c) 2006 - 2014, 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. >> +// >> +// **/ >> + >> + >> +#string STR_MODULE_ABSTRACT #language en-US >> "Instance of Debug Library based on Serial Port Library" >> + >> +#string STR_MODULE_DESCRIPTION #language en-US >> "It uses Print Library to produce formatted output >> strings to a serial port device." >> + >> -- >> 2.11.0 >