From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by mx.groups.io with SMTP id smtpd.web12.4851.1657782260581647435 for ; Thu, 14 Jul 2022 00:04:21 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=WbuE6yzh; spf=pass (domain: intel.com, ip: 134.134.136.65, mailfrom: ray.ni@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1657782260; x=1689318260; h=from:to:cc:subject:date:message-id:references: in-reply-to:content-transfer-encoding:mime-version; bh=bm0aaPaKsfikbYAIqRAIxLmclveA6PbfiA5E3t+KmxE=; b=WbuE6yzhPjG2oCPtESaZKiEM84aStpUBD+lRvJ4B4gS9y+Z8c+UDJEmg dajy4MjFUys2F/x7duka0A0ts9swqWIIEUlpDWXpicbHZ8z3H6v9yc3p8 52hzs14Tt8ABzZnJIvWmCA7KJchxtydWyrW/WGLtBOUO4UQtLS4Y2vWxO rRzdQMx/6WhfZxFceV5FmV8BLhZ46L2BSl6wqfnqZiadDhdJspVpGlEm7 HSmL10HUs+pkedFERKaRxEWKFU827roarjq9F+mT46avMs1FB9hhZ01VZ KPkoTiyIZ1rtocYifgu3xo+seE+WPF6nyWYnCk7WLZz1jkyVQ3WrKQDl8 A==; X-IronPort-AV: E=McAfee;i="6400,9594,10407"; a="286575121" X-IronPort-AV: E=Sophos;i="5.92,269,1650956400"; d="scan'208";a="286575121" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Jul 2022 00:04:12 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,269,1650956400"; d="scan'208";a="628601202" Received: from fmsmsx604.amr.corp.intel.com ([10.18.126.84]) by orsmga001.jf.intel.com with ESMTP; 14 Jul 2022 00:04:12 -0700 Received: from fmsmsx609.amr.corp.intel.com (10.18.126.89) by fmsmsx604.amr.corp.intel.com (10.18.126.84) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.27; Thu, 14 Jul 2022 00:04:12 -0700 Received: from FMSEDG603.ED.cps.intel.com (10.1.192.133) by fmsmsx609.amr.corp.intel.com (10.18.126.89) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.27 via Frontend Transport; Thu, 14 Jul 2022 00:04:12 -0700 Received: from NAM11-BN8-obe.outbound.protection.outlook.com (104.47.58.169) by edgegateway.intel.com (192.55.55.68) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2308.27; Thu, 14 Jul 2022 00:04:11 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=UZCEbv1tbG2puC2eE2MX+g/m4xWAAQWma9L7T80bECglCopdv67HDOR3gX5F7AaQKFzMZZgtntDJ4AzMNFQKX+/IsumHnuci02Rmeo8XztL21xH3CIdgNlFHYduk/jIfDjKAfn4yIgSfBmEuNyqdzaugNveUi36P9ZDoRe8IdCmSw9cz3fjG1nlIRFqCA24eQyB4pIwacvDc5bMtIPVndlVq1ns/wVS6QuNkqIe40cthrKsqZKJ6+dPvrG5gQi1zY8fNnNzUiw9G2ATIpYAVL4kekuGtdwN9iDmbXvt39w+1ZKG7Ly0Op/TlmEBhaH3/aCk1U3vsxQOH8wyUs7l5yw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=k9f2Pt2Nmx4aHj4DAU+XL25PxdAKh8vsTu7scaw0yNI=; b=gOKFL+oqvtiCJn3MOG2/iis1CNTzfT85POE2/TnGjR1MELhqv5DHI/7DA14/baqOXSVMnIl0K9FWWKxuc4oAjvZewxqwQ2LuA5pYj+kG6Hv9Yc2/J5ZIezsji2SvSiUPOT2Oo2mZVp7jgmSh1msZwrlqxph5mBwUuEDujxhbjeqzhQDXVgUmqHE2rLoIrVJoWJ5sAUWI5G623VdWhvYCcP+YnUWols8LcNt0qgQuwyUuX2dOPIBzx+4kYEPPZ/gOvNUlkfsUM1P/IoPGpvZT1s1mKxxUbjLNhyuYpaw7/oLpSrWNOXlOCjrFW+J9RWHKajiuM0BigzGaRuSNTGcYIQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none Received: from MWHPR11MB1631.namprd11.prod.outlook.com (2603:10b6:301:10::10) by DM6PR11MB2585.namprd11.prod.outlook.com (2603:10b6:5:ce::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5417.25; Thu, 14 Jul 2022 07:04:07 +0000 Received: from MWHPR11MB1631.namprd11.prod.outlook.com ([fe80::991b:97a0:7836:5174]) by MWHPR11MB1631.namprd11.prod.outlook.com ([fe80::991b:97a0:7836:5174%10]) with mapi id 15.20.5417.026; Thu, 14 Jul 2022 07:04:07 +0000 From: "Ni, Ray" To: "Sravanthi, K KavyaX" , "devel@edk2.groups.io" CC: "Dong, Guo" , Maurice Ma , "You, Benjamin" , "Rhodes, Sean" Subject: Re: [PATCH 2/3] UefiPayloadPkg: Implement a new SerialPortLib instance Thread-Topic: [PATCH 2/3] UefiPayloadPkg: Implement a new SerialPortLib instance Thread-Index: AQHYlzqhvgaHw2TNv0u4Sa+FKFM/Aq19cIxQ Date: Thu, 14 Jul 2022 07:04:07 +0000 Message-ID: References: <20220714043104.1813-1-k.kavyax.sravanthi@intel.com> <20220714043104.1813-2-k.kavyax.sravanthi@intel.com> In-Reply-To: <20220714043104.1813-2-k.kavyax.sravanthi@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=intel.com; x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 42617283-4e42-4404-04fc-08da65670b40 x-ms-traffictypediagnostic: DM6PR11MB2585:EE_ x-ld-processed: 46c98d88-e344-4ed4-8496-4ed7712e255d,ExtAddr x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: w7p2yDHao8Cz5o1v+KeWXOR9xaZerpeyYlvD4vDzubQ/ABD9e5A1vJisWfxDlmDa5Bqs4VZZZclO++yd0LPN2YW6pl7jRD+R4GmegCLTK3x+SBKrIxFdfKveEPUrijVez+r64tK/Yo/Tt6GKIpdrp/TtqHk3OhaiuJ8+mx3IX+cbK9EQKC7JcVaJ8Obq0y84S/nZyYLhnPESNn2xHgYm/8Rj6+EVIK9uW6AMmkCfZG1i5ai5BWQTYsYqk7GlSTa2KrshZQ/bXgfD7wBUhU0rjD9cw3WNaNbEi3jzJshKOR1NVddCpIJxCjSwAsZyrvEFQm1HlBuCLsFOyN9GxaNCNyXdn+YWvqMyqFzscsFEjUz3NRdbB1V39a4n9ONRADQch/dCB/GqGUEhRs9GdVY1k1dpSIe0Kxv3taK49tWAZhGEYb1/Eeh9X0K3ula2cszlFTRNG42T73ZpHMc+ohjgUyvuX0D06vbmd27TMipbTQN6ZwupQGJUeaOQrc9t+PRzbB7G16GHvCmbvTlyMQhkZNwhl2gGLNC7cCDZihvy/UbPAabBOn6nqotitAxTglQ1uhY5lKKG9MLuUW+iv+l2Up6LKRMfs0BZ1jDIY2U2/Dn5eMt6rm84bNDTDTb5I+Ribbz87rIzWz/rivyFz+BuNocI14MPsrvncDr2ckLVGM4tYaKMgVIFA+waK3kP8FnESQEhnxGbUCHQ9lYHvnzVRvwC9aHaLEKdvZBvpxhzB7sY5XpBqtTNWwSYXK1GAFz/tJAAa2ywDRWuJFXc0dUBBc8XKjJKF00a6VE3yOEHqzgoqoJ5gxXn7W3DeQyAvMA2 x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:MWHPR11MB1631.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230016)(376002)(366004)(136003)(396003)(346002)(39860400002)(122000001)(55016003)(30864003)(52536014)(316002)(8936002)(38100700002)(5660300002)(83380400001)(6506007)(7696005)(186003)(66476007)(4326008)(33656002)(8676002)(53546011)(76116006)(86362001)(54906003)(26005)(9686003)(110136005)(38070700005)(478600001)(64756008)(66556008)(66446008)(71200400001)(66946007)(2906002)(82960400001)(41300700001)(579004)(559001);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?1hXv+xPbswvZIhamo3fwmCR2BBn0KTpRmgp1qHndBBE234ax4hwwaT/IVkX4?= =?us-ascii?Q?fzghTiFGZDF8vdwjDzNgIQoh0YNEUreDdyFBEL6DXE9ZQ8f0oPpwLmapy98Q?= =?us-ascii?Q?nM2u4ixZFe71AtWCfg4UKd8I14IDGfb53Q1RH7VWRfKehHt/guc2hG7VRSyN?= =?us-ascii?Q?Oq7sDInfourJp9oZse+ttaHC0ozBgZjYypz48jNA46mgb7Z47w/E0QRvw60V?= =?us-ascii?Q?ZSzPPMkO8BDfi0wxdiF3UXd4lAz+QfBYbjCd0ZJzn8pDUH3A6yYYNsz7V7Bg?= =?us-ascii?Q?Sc7np94lPSDrupZWvn4PrEk0JIRx2ZBtFk4WiC8gq7UILs3ACtipqfzYb9aA?= =?us-ascii?Q?Grex/CVk3/Y6OUnNFQxRr5yEB+Z8+WlnHc56qhlIa6fBIJsa3iJTBdKIbQQr?= =?us-ascii?Q?i1yDpIE5KjWvIQ+dy9i8U+KgoG5Y1R/5GgSE63GpAFH+gfEdTDdoMEbtoRAq?= =?us-ascii?Q?Vicvdmioy5Nt6xPHCMhUITq64Nquv7XNAtjKm8HP+php7tRA5EVTSjbHEphu?= =?us-ascii?Q?KjnKc3VdBAa+/emZelkqS1aoxXNGo1bxoPT5P1zLEtwpLcMfmt/gJsSrwzkg?= =?us-ascii?Q?4p7A4lTINDG+gYdMlJXb+SsqN3yABAk26auM6DRpKKqtEhAG5wu88UQNCFn2?= =?us-ascii?Q?vrbBBZ01KjoGcGIeYpDrT/W/9K1aIraXXBjytkJqLSReg13AhdbcHvIeCPuX?= =?us-ascii?Q?Wj6ofVGKLLBgNupyqQG93ExrFBnr8g6TBi10tD4HjSwwEK2G54I8gLHZrDCu?= =?us-ascii?Q?/VniiDzAwGZhb5D2lXlAIj/p9kz6zH+uxKFPAJQVoLfoqr9a1Kr+D318fW3B?= =?us-ascii?Q?/fnPQJCHAr7CO+ZTaG1I1xTjhTYydkcjwnQyHRRqWIaEpho0gO09Zvm34Juq?= =?us-ascii?Q?tuVCVgoODtKgkQOr9Xlmf7+ZIhrLToIA5DD7x6hxQ2wg9ZhE2b//RnH5kTXb?= =?us-ascii?Q?O3dqyAQKAj98cK0NuqQ/FlCWz4N1YZXQ3ofAYitoJUyIJKn8Vr5+1cVzA2xr?= =?us-ascii?Q?yWwxOJw1cSzgWYwGx4TAwUSi+zeJpaZpIsabDhK4E93p9xGAiRqLBKUrSP/M?= =?us-ascii?Q?4m8tFUY8zlhlbSb7DhDa6tiMMWu1iYgqruL0i7GErZJnKl376tuLsG+Pw3sG?= =?us-ascii?Q?zibORDolJLb/48XmS8ocftZYvDL8I9MlUtfdHvTLLPqkBEN4MrwplqENJuxF?= =?us-ascii?Q?Ewtxp89x8sy1/nWTVq/jON7r+lu7s52HULXSYh0ttQZr8JKY7AuYkw6yC94J?= =?us-ascii?Q?q0lOoLJrE7Ght4Uf61jfOAVMesnXnwR8n1YZPkBM5milD1cLAe3j9nocJec6?= =?us-ascii?Q?c7tpZvRC8isfR/vIvXACgY86anEw0BRkND94qiYTqa0kFuIbYWWf1jYPp3Bn?= =?us-ascii?Q?4ZbOJUL+Q/KlTHrMdVe6WgqCgkN0hIuqjLMXMejSKjB4Vel3g6VyAqbmUwnT?= =?us-ascii?Q?xqbnFualbHHo7AcHhXDOJQvQtR2kvvYMG5AmGc9UEyOFIn8ZD25Hp+Ca1HTG?= =?us-ascii?Q?sZealRn6VI8Dm6W5gcU3olrjf6PiYlEkLnzxtjuPisVutO/Gnv1e6zUCnvm4?= =?us-ascii?Q?fVpZmnAACTBoJAM1PSc=3D?= MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: MWHPR11MB1631.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 42617283-4e42-4404-04fc-08da65670b40 X-MS-Exchange-CrossTenant-originalarrivaltime: 14 Jul 2022 07:04:07.0503 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: Vo8rm514YTvBwHXHRk2tR0FUq7BQUOoHZP5E/zbKdbxuuK891KR3yt6mkL1F7jSqmcPe97byZwhaxFvSQ6fuhg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR11MB2585 Return-Path: ray.ni@intel.com X-OriginatorOrg: intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable The implementation looks good. But it limits the usage of SerialPortRead/Write to be called only from BSP = because GetFirstGuidHob() can not be called from APs. An alternative implementation is to cache the UART instances data into a li= brary global array so SerialPortRead/Write don't need to call GetFirstGuidH= ob() again. Such change allows APs call the APIs. > -----Original Message----- > From: Sravanthi, K KavyaX > Sent: Thursday, July 14, 2022 12:31 PM > To: devel@edk2.groups.io > Cc: Sravanthi, K KavyaX ; Dong, Guo ; Ni, Ray ; > Maurice Ma ; You, Benjamin = ; Rhodes, Sean > > Subject: [PATCH 2/3] UefiPayloadPkg: Implement a new SerialPortLib instan= ce >=20 > Add new Serial port library instance that consumes the HOB defined > in MdeModulePkg/Include/UniversalPayload/SerialPortInfo.h to support > multiple UART's. >=20 > Cc: Guo Dong > Cc: Ray Ni > Cc: Maurice Ma > Cc: Benjamin You > Cc: Sean Rhodes > Signed-off-by: Kavya > --- > UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.c | 8= 02 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.inf | = 39 > +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 841 insertions(+) >=20 > diff --git a/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLi= bHob.c > b/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.c > new file mode 100644 > index 0000000000..6f62b2a5d2 > --- /dev/null > +++ b/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.c > @@ -0,0 +1,802 @@ > +/** @file > + UART Serial Port library functions. > + > + Copyright (c) 2022, Intel Corporation. All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +// > +// 16550 UART register offsets and bitfields > +// > +#define R_UART_RXBUF 0 // LCR_DLAB =3D 0 > +#define R_UART_TXBUF 0 // LCR_DLAB =3D 0 > +#define R_UART_BAUD_LOW 0 // LCR_DLAB =3D 1 > +#define R_UART_BAUD_HIGH 1 // LCR_DLAB =3D 1 > +#define R_UART_IER 1 // LCR_DLAB =3D 0 > +#define R_UART_FCR 2 > +#define B_UART_FCR_FIFOE BIT0 > +#define B_UART_FCR_FIFO64 BIT5 > +#define R_UART_LCR 3 > +#define B_UART_LCR_DLAB BIT7 > +#define R_UART_MCR 4 > +#define B_UART_MCR_DTRC BIT0 > +#define B_UART_MCR_RTS BIT1 > +#define R_UART_LSR 5 > +#define B_UART_LSR_RXRDY BIT0 > +#define B_UART_LSR_TXRDY BIT5 > +#define B_UART_LSR_TEMT BIT6 > +#define R_UART_MSR 6 > +#define B_UART_MSR_CTS BIT4 > +#define B_UART_MSR_DSR BIT5 > +#define B_UART_MSR_RI BIT6 > +#define B_UART_MSR_DCD BIT7 > + > +/** > + Reads an 8-bit register. If UseMmio is TRUE, then the value is read fr= om > + MMIO space. If UseMmio is FALSE, then the value is read from I/O space= . The > + parameter Offset is added to the base address of the register. > + > + @param Base The base address register of UART device. > + @param Offset The offset of the register to read. > + @param UseMmio Check if value has to be read from MMIO space or IO s= pace. > + > + @return The value read from the register. > + > +**/ > +UINT8 > +SerialPortReadRegister ( > + UINTN Base, > + UINTN Offset, > + BOOLEAN UseMmio > + ) > +{ > + if (UseMmio) { > + return MmioRead8 (Base + Offset/4); > + } else { > + return IoRead8 (Base + Offset); > + } > +} > + > +/** > + Writes an 8-bit register.. If UseMmio is TRUE, then the value is writt= en to > + MMIO space. If UseMmio is FALSE, then the value is written to I/O spac= e. The > + parameter Offset is added to the base address of the registers. > + > + @param Base The base address register of UART device. > + @param Offset The offset of the register to write. > + @param Value Value to be written. > + @param UseMmio Check if value has to be written to MMIO space or IO = space. > + > + @return The value written to the register. > + > +**/ > +UINT8 > +SerialPortWriteRegister ( > + UINTN Base, > + UINTN Offset, > + UINT8 Value, > + BOOLEAN UseMmio > + ) > +{ > + if (UseMmio) { > + return MmioWrite8 (Base + Offset/4, Value); > + } else { > + return IoWrite8 (Base + Offset, Value); > + } > +} > + > +/** > + Initialize the serial device hardware. > + > + If no initialization is required, then return RETURN_SUCCESS. > + If the serial device was successfully initialized, then return RETURN_= SUCCESS. > + If the serial device could not be initialized, then return RETURN_DEVI= CE_ERROR. > + If gUniversalPayloadSerialPortInfoGuid not found, then return RETURN_N= OT_FOUND. > + > + @retval RETURN_SUCCESS The serial device was initialized. > + @retval RETURN_DEVICE_ERROR The serial device could not be initializ= ed. > + @retval RETURN_NOT_FOUND GuidHob not found. > + > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortInitialize ( > + VOID > + ) > +{ > + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN SerialRegisterBase; > + UINT32 Divisor; > + UINT32 CurrentDivisor; > + UINT32 BaudRate; > + BOOLEAN Initialized; > + BOOLEAN MmioEnable; > + > + GuidHob =3D GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); > + if (GuidHob =3D=3D NULL) { > + return RETURN_NOT_FOUND; > + } > + while (GuidHob !=3D NULL) { > + SerialPortInfo =3D (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HO= B_DATA (GuidHob); > + SerialRegisterBase =3D SerialPortInfo->RegisterBase; > + MmioEnable =3D SerialPortInfo->UseMmio; > + BaudRate =3D SerialPortInfo->BaudRate; > + > + if (SerialRegisterBase =3D=3D 0) { > + return RETURN_DEVICE_ERROR; > + } > + > + Divisor =3D PcdGet32 (PcdSerialClockRate) / (BaudRate * 16); > + if ((PcdGet32 (PcdSerialClockRate) % (BaudRate * 16)) >=3D BaudRate = * 8) { > + Divisor++; > + } > + > + // > + // See if the serial port is already initialized > + // > + Initialized =3D TRUE; > + if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LCR, MmioEna= ble) & 0x3F) !=3D (PcdGet8 (PcdSerialLineControl) > & 0x3F)) { > + Initialized =3D FALSE; > + } > + > + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(Ser= ialPortReadRegister (SerialRegisterBase, > R_UART_LCR, MmioEnable) | B_UART_LCR_DLAB), MmioEnable); > + CurrentDivisor =3D SerialPortReadRegister (SerialRegisterBase, R_U= ART_BAUD_HIGH, MmioEnable) << 8; > + CurrentDivisor |=3D (UINT32)SerialPortReadRegister (SerialRegisterBa= se, R_UART_BAUD_LOW, MmioEnable); > + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(Ser= ialPortReadRegister (SerialRegisterBase, > R_UART_LCR, MmioEnable) & ~B_UART_LCR_DLAB), MmioEnable); > + if (CurrentDivisor !=3D Divisor) { > + Initialized =3D FALSE; > + } > + > + if (Initialized) { > + return RETURN_SUCCESS; > + } > + > + // > + // Wait for the serial port to be ready. > + // Verify that both the transmit FIFO and the shift register are emp= ty. > + // > + while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR, Mmio= Enable) & (B_UART_LSR_TEMT | > B_UART_LSR_TXRDY)) !=3D (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) { > + } > + > + // > + // Configure baud rate > + // > + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_= DLAB, MmioEnable); > + SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT= 8)(Divisor >> 8), MmioEnable); > + SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8= )(Divisor & 0xff), MmioEnable); > + > + // > + // Clear DLAB and configure Data Bits, Parity, and Stop Bits. > + // Strip reserved bits from PcdSerialLineControl > + // > + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(Pcd= Get8 (PcdSerialLineControl) & 0x3F), > MmioEnable); > + > + // > + // Enable and reset FIFOs > + // Strip reserved bits from PcdSerialFifoControl > + // > + SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, 0x00, MmioE= nable); > + SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, (UINT8)(Pcd= Get8 (PcdSerialFifoControl) & > (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)), MmioEnable); > + > + // > + // Set FIFO Polled Mode by clearing IER after setting FCR > + // > + SerialPortWriteRegister (SerialRegisterBase, R_UART_IER, 0x00, MmioE= nable); > + > + // > + // Put Modem Control Register(MCR) into its reset state of 0x00. > + // > + SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, 0x00, MmioE= nable); > + > + GuidHob =3D GET_NEXT_HOB (GuidHob); > + GuidHob =3D GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, Gu= idHob); > + } > + > + return RETURN_SUCCESS; > +} > + > +/** > + Write data from buffer to serial device. > + > + Writes NumberOfBytes data bytes from Buffer to the serial device. > + The number of bytes actually written to the serial device is returned. > + If the return value is less than NumberOfBytes, then the write operati= on failed. > + > + If Buffer is NULL, then return 0. > + > + If NumberOfBytes is zero, then return 0. > + > + @param Buffer Pointer to the data buffer to be written. > + @param NumberOfBytes Number of bytes to written to the serial devi= ce. > + > + @retval 0 NumberOfBytes is 0. > + @retval >0 The number of bytes written to the serial dev= ice. > + If this value is less than NumberOfBytes, the= n the write operation failed. > + > +**/ > +UINTN > +EFIAPI > +SerialPortWrite ( > + IN UINT8 *Buffer, > + IN UINTN NumberOfBytes > + ) > +{ > + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN BaseAddress; > + BOOLEAN UseMmio; > + UINTN BytesLeft; > + UINTN Index; > + UINTN FifoSize; > + UINT8 *DataBuffer; > + > + if (Buffer =3D=3D NULL || NumberOfBytes =3D=3D 0) { > + return 0; > + } > + > + // > + // Compute the maximum size of the Tx FIFO > + // > + FifoSize =3D 1; > + if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFOE) !=3D 0) { > + if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFO64) =3D=3D 0) { > + FifoSize =3D 16; > + } else { > + FifoSize =3D PcdGet32 (PcdSerialExtendedTxFifoSize); > + } > + } > + > + GuidHob =3D GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); > + while (GuidHob !=3D NULL) { > + SerialPortInfo =3D (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HO= B_DATA (GuidHob); > + BaseAddress =3D SerialPortInfo->RegisterBase; > + UseMmio =3D SerialPortInfo->UseMmio; > + > + DataBuffer =3D Buffer; > + BytesLeft =3D NumberOfBytes; > + > + while (BytesLeft !=3D 0) { > + // > + // Fill the entire Tx FIFO > + // > + for (Index =3D 0; Index < FifoSize && BytesLeft !=3D 0; Index++, B= ytesLeft--, DataBuffer++) { > + // > + // Write byte to the transmit buffer. > + // > + SerialPortWriteRegister (BaseAddress, R_UART_TXBUF, *DataBuffer,= UseMmio); > + } > + MicroSecondDelay (20); > + } > + GuidHob =3D GET_NEXT_HOB (GuidHob); > + GuidHob =3D GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, Gu= idHob); > + } > + > + return NumberOfBytes; > +} > + > +/** > + Reads data from a serial device into a buffer. > + > + @param Buffer Pointer to the data buffer to store the data = read from the serial device. > + @param NumberOfBytes Number of bytes to read from the serial devic= e. > + > + @retval 0 NumberOfBytes is 0. > + @retval >0 The number of bytes read from the serial devi= ce. > + If this value is less than NumberOfBytes, the= n the read operation failed. > + > +**/ > +UINTN > +EFIAPI > +SerialPortRead ( > + OUT UINT8 *Buffer, > + IN UINTN NumberOfBytes > + ) > +{ > + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN BaseAddress; > + BOOLEAN UseMmio; > + UINT8 *DataBuffer; > + UINTN BytesLeft; > + UINTN Result; > + UINT8 Mcr; > + > + if (Buffer =3D=3D NULL) { > + return 0; > + } > + > + GuidHob =3D GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); > + while (GuidHob !=3D NULL) { > + SerialPortInfo =3D (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HO= B_DATA (GuidHob); > + BaseAddress =3D SerialPortInfo->RegisterBase; > + UseMmio =3D SerialPortInfo->UseMmio; > + > + DataBuffer =3D Buffer; > + BytesLeft =3D NumberOfBytes; > + > + if (BaseAddress =3D=3D 0) { > + return 0; > + } > + > + Mcr =3D (UINT8)(SerialPortReadRegister (BaseAddress, R_UART_MCR, Use= Mmio) & ~B_UART_MCR_RTS); > + > + for (Result =3D 0; BytesLeft-- !=3D 0; Result++, DataBuffer++) { > + // > + // Wait for the serial port to have some data. > + // > + while ((SerialPortReadRegister (BaseAddress, R_UART_LSR, UseMmio) = & B_UART_LSR_RXRDY) =3D=3D 0) { > + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { > + // > + // Set RTS to let the peer send some data > + // > + SerialPortWriteRegister (BaseAddress, R_UART_MCR, (UINT8)(Mcr = | B_UART_MCR_RTS), UseMmio); > + } > + } > + > + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { > + // > + // Clear RTS to prevent peer from sending data > + // > + SerialPortWriteRegister (BaseAddress, R_UART_MCR, Mcr, UseMmio); > + } > + > + // > + // Read byte from the receive buffer. > + // > + *DataBuffer =3D SerialPortReadRegister (BaseAddress, R_UART_RXBUF,= UseMmio); > + } > + > + GuidHob =3D GET_NEXT_HOB (GuidHob); > + GuidHob =3D GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, Gu= idHob); > + } > + > + return Result; > +} > + > +/** > + Polls a serial device to see if there is any data waiting to be read. > + > + Polls a serial device to see if there is any data waiting to be read. > + If there is data waiting to be read from the serial device, then TRUE = is returned. > + If there is no data waiting to be read from the serial device, then FA= LSE is returned. > + > + @retval TRUE Data is waiting to be read from the serial de= vice. > + @retval FALSE There is no data waiting to be read from the = serial device. > + > +**/ > +BOOLEAN > +EFIAPI > +SerialPortPoll ( > + VOID > + ) > +{ > + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN BaseAddress; > + BOOLEAN UseMmio; > + > + GuidHob =3D GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); > + while (GuidHob !=3D NULL) { > + SerialPortInfo =3D (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HO= B_DATA (GuidHob); > + BaseAddress =3D SerialPortInfo->RegisterBase; > + UseMmio =3D SerialPortInfo->UseMmio; > + > + if (BaseAddress =3D=3D 0) { > + return FALSE; > + } > + > + // > + // Read the serial port status > + // > + if ((SerialPortReadRegister (BaseAddress, R_UART_LSR, UseMmio) & B_U= ART_LSR_RXRDY) !=3D 0) { > + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { > + // > + // Clear RTS to prevent peer from sending data > + // > + SerialPortWriteRegister (BaseAddress, R_UART_MCR, (UINT8)(Serial= PortReadRegister (BaseAddress, R_UART_MCR, > UseMmio) & ~B_UART_MCR_RTS), UseMmio); > + } > + return TRUE; > + } > + > + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { > + // > + // Set RTS to let the peer send some data > + // > + SerialPortWriteRegister (BaseAddress, R_UART_MCR, (UINT8)(SerialPo= rtReadRegister (BaseAddress, R_UART_MCR, > UseMmio) | B_UART_MCR_RTS), UseMmio); > + } > + > + GuidHob =3D GET_NEXT_HOB (GuidHob); > + GuidHob =3D GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, Gu= idHob); > + } > + return FALSE; > +} > + > +/** > + Sets the control bits on a serial device. > + > + @param Control Sets the bits of Control that are settab= le. > + > + @retval RETURN_SUCCESS The new control bits were set on the ser= ial device. > + @retval RETURN_UNSUPPORTED The serial device does not support this = operation. > + @retval RETURN_DEVICE_ERROR The serial device is not functioning cor= rectly. > + @retval RETURN_NOT_FOUND GuidHob not found. > + > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortSetControl ( > + IN UINT32 Control > + ) > +{ > + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN BaseAddress; > + BOOLEAN UseMmio; > + UINT8 Mcr; > + > + GuidHob =3D GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); > + if (GuidHob =3D=3D NULL) { > + return RETURN_NOT_FOUND; > + } > + while (GuidHob !=3D NULL) { > + SerialPortInfo =3D (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HO= B_DATA (GuidHob); > + BaseAddress =3D SerialPortInfo->RegisterBase; > + UseMmio =3D SerialPortInfo->UseMmio; > + > + if (BaseAddress =3D=3D 0) { > + return RETURN_UNSUPPORTED; > + } > + > + // > + // First determine the parameter is invalid. > + // > + if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMI= NAL_READY | > + EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) !=3D 0) > + { > + return RETURN_UNSUPPORTED; > + } > + > + // > + // Read the Modem Control Register. > + // > + Mcr =3D SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio); > + Mcr &=3D (~(B_UART_MCR_DTRC | B_UART_MCR_RTS)); > + > + if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) =3D=3D EFI_SERIAL_DAT= A_TERMINAL_READY) { > + Mcr |=3D B_UART_MCR_DTRC; > + } > + > + if ((Control & EFI_SERIAL_REQUEST_TO_SEND) =3D=3D EFI_SERIAL_REQUEST= _TO_SEND) { > + Mcr |=3D B_UART_MCR_RTS; > + } > + > + // > + // Write the Modem Control Register. > + // > + SerialPortWriteRegister (BaseAddress, R_UART_MCR, Mcr, UseMmio); > + > + GuidHob =3D GET_NEXT_HOB (GuidHob); > + GuidHob =3D GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, Gu= idHob); > + } > + > + return RETURN_SUCCESS; > +} > + > +/** > + Retrieve the status of the control bits on a serial device. > + > + @param Control A pointer to return the current control = signals from the serial device. > + > + @retval RETURN_SUCCESS The control bits were read from the seri= al device. > + @retval RETURN_UNSUPPORTED The serial device does not support this = operation. > + @retval RETURN_DEVICE_ERROR The serial device is not functioning cor= rectly. > + @retval RETURN_NOT_FOUND GuidHob not found. > + > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortGetControl ( > + OUT UINT32 *Control > + ) > +{ > + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN BaseAddress; > + BOOLEAN UseMmio; > + UINT8 Msr; > + UINT8 Mcr; > + UINT8 Lsr; > + > + GuidHob =3D GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); > + if (GuidHob =3D=3D NULL) { > + return RETURN_NOT_FOUND; > + } > + while (GuidHob !=3D NULL) { > + SerialPortInfo =3D (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HO= B_DATA (GuidHob); > + BaseAddress =3D SerialPortInfo->RegisterBase; > + UseMmio =3D SerialPortInfo->UseMmio; > + > + if (BaseAddress =3D=3D 0) { > + return RETURN_UNSUPPORTED; > + } > + > + *Control =3D 0; > + > + // > + // Read the Modem Status Register. > + // > + Msr =3D SerialPortReadRegister (BaseAddress, R_UART_MSR, UseMmio); > + > + if ((Msr & B_UART_MSR_CTS) =3D=3D B_UART_MSR_CTS) { > + *Control |=3D EFI_SERIAL_CLEAR_TO_SEND; > + } > + > + if ((Msr & B_UART_MSR_DSR) =3D=3D B_UART_MSR_DSR) { > + *Control |=3D EFI_SERIAL_DATA_SET_READY; > + } > + > + if ((Msr & B_UART_MSR_RI) =3D=3D B_UART_MSR_RI) { > + *Control |=3D EFI_SERIAL_RING_INDICATE; > + } > + > + if ((Msr & B_UART_MSR_DCD) =3D=3D B_UART_MSR_DCD) { > + *Control |=3D EFI_SERIAL_CARRIER_DETECT; > + } > + > + // > + // Read the Modem Control Register. > + // > + Mcr =3D SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio); > + > + if ((Mcr & B_UART_MCR_DTRC) =3D=3D B_UART_MCR_DTRC) { > + *Control |=3D EFI_SERIAL_DATA_TERMINAL_READY; > + } > + > + if ((Mcr & B_UART_MCR_RTS) =3D=3D B_UART_MCR_RTS) { > + *Control |=3D EFI_SERIAL_REQUEST_TO_SEND; > + } > + > + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { > + *Control |=3D EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; > + } > + > + // > + // Read the Line Status Register. > + // > + Lsr =3D SerialPortReadRegister (BaseAddress, R_UART_LSR, UseMmio); > + > + if ((Lsr & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) =3D=3D (B_UART_LSR_= TEMT | B_UART_LSR_TXRDY)) { > + *Control |=3D EFI_SERIAL_OUTPUT_BUFFER_EMPTY; > + } > + > + if ((Lsr & B_UART_LSR_RXRDY) =3D=3D 0) { > + *Control |=3D EFI_SERIAL_INPUT_BUFFER_EMPTY; > + } > + > + GuidHob =3D GET_NEXT_HOB (GuidHob); > + GuidHob =3D GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, Gu= idHob); > + } > + > + return RETURN_SUCCESS; > +} > + > +/** > + Sets the baud rate, receive FIFO depth, transmit/receice time out, par= ity, > + data bits, and stop bits on a serial device. > + > + @param BaudRate The requested baud rate. A BaudRate value of= 0 will use the > + device's default interface speed. > + On output, the value actually set. > + @param ReveiveFifoDepth The requested depth of the FIFO on the recei= ve side of the > + serial interface. A ReceiveFifoDepth value o= f 0 will use > + the device's default FIFO depth. > + On output, the value actually set. > + @param Timeout The requested time out for a single characte= r in microseconds. > + This timeout applies to both the transmit an= d receive side of the > + interface. A Timeout value of 0 will use the= device's default time > + out value. > + On output, the value actually set. > + @param Parity The type of parity to use on this serial dev= ice. A Parity value of > + DefaultParity will use the device's default = parity value. > + On output, the value actually set. > + @param DataBits The number of data bits to use on the serial= device. A DataBits > + vaule of 0 will use the device's default dat= a bit setting. > + On output, the value actually set. > + @param StopBits The number of stop bits to use on this seria= l device. A StopBits > + value of DefaultStopBits will use the device= 's default number of > + stop bits. > + On output, the value actually set. > + > + @retval RETURN_SUCCESS The new attributes were set on the s= erial device. > + @retval RETURN_UNSUPPORTED The serial device does not support t= his operation. > + @retval RETURN_INVALID_PARAMETER One or more of the attributes has an= unsupported value. > + @retval RETURN_DEVICE_ERROR The serial device is not functioning= correctly. > + @retval RETURN_NOT_FOUND GuidHob not found. > + > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortSetAttributes ( > + IN OUT UINT64 *BaudRate, > + IN OUT UINT32 *ReceiveFifoDepth, > + IN OUT UINT32 *Timeout, > + IN OUT EFI_PARITY_TYPE *Parity, > + IN OUT UINT8 *DataBits, > + IN OUT EFI_STOP_BITS_TYPE *StopBits > + ) > +{ > + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN BaseAddress; > + BOOLEAN UseMmio; > + UINT32 SerialBaudRate; > + UINTN Divisor; > + UINT8 Lcr; > + UINT8 LcrData; > + UINT8 LcrParity; > + UINT8 LcrStop; > + > + GuidHob =3D GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); > + if (GuidHob =3D=3D NULL) { > + return RETURN_NOT_FOUND; > + } > + while (GuidHob !=3D NULL) { > + SerialPortInfo =3D (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HO= B_DATA (GuidHob); > + BaseAddress =3D SerialPortInfo->RegisterBase; > + UseMmio =3D SerialPortInfo->UseMmio; > + > + if (BaseAddress =3D=3D 0) { > + return RETURN_UNSUPPORTED; > + } > + > + // > + // Check for default settings and fill in actual values. > + // > + if (*BaudRate =3D=3D 0) { > + *BaudRate =3D SerialPortInfo->BaudRate; > + } > + > + SerialBaudRate =3D (UINT32)*BaudRate; > + > + if (*DataBits =3D=3D 0) { > + LcrData =3D (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3); > + *DataBits =3D LcrData + 5; > + } else { > + if ((*DataBits < 5) || (*DataBits > 8)) { > + return RETURN_INVALID_PARAMETER; > + } > + > + // > + // Map 5..8 to 0..3 > + // > + LcrData =3D (UINT8)(*DataBits - (UINT8)5); > + } > + > + if (*Parity =3D=3D DefaultParity) { > + LcrParity =3D (UINT8)((PcdGet8 (PcdSerialLineControl) >> 3) & 0x7)= ; > + switch (LcrParity) { > + case 0: > + *Parity =3D NoParity; > + break; > + > + case 3: > + *Parity =3D EvenParity; > + break; > + > + case 1: > + *Parity =3D OddParity; > + break; > + > + case 7: > + *Parity =3D SpaceParity; > + break; > + > + case 5: > + *Parity =3D MarkParity; > + break; > + > + default: > + break; > + } > + } else { > + switch (*Parity) { > + case NoParity: > + LcrParity =3D 0; > + break; > + > + case EvenParity: > + LcrParity =3D 3; > + break; > + > + case OddParity: > + LcrParity =3D 1; > + break; > + > + case SpaceParity: > + LcrParity =3D 7; > + break; > + > + case MarkParity: > + LcrParity =3D 5; > + break; > + > + default: > + return RETURN_INVALID_PARAMETER; > + } > + } > + > + if (*StopBits =3D=3D DefaultStopBits) { > + LcrStop =3D (UINT8)((PcdGet8 (PcdSerialLineControl) >> 2) & 0x1); > + switch (LcrStop) { > + case 0: > + *StopBits =3D OneStopBit; > + break; > + > + case 1: > + if (*DataBits =3D=3D 5) { > + *StopBits =3D OneFiveStopBits; > + } else { > + *StopBits =3D TwoStopBits; > + } > + > + break; > + > + default: > + break; > + } > + } else { > + switch (*StopBits) { > + case OneStopBit: > + LcrStop =3D 0; > + break; > + > + case OneFiveStopBits: > + case TwoStopBits: > + LcrStop =3D 1; > + break; > + > + default: > + return RETURN_INVALID_PARAMETER; > + } > + } > + > + // > + // Calculate divisor for baud generator > + // Ref_Clk_Rate / Baud_Rate / 16 > + // > + Divisor =3D PcdGet32 (PcdSerialClockRate) / (SerialBaudRate * 16); > + if ((PcdGet32 (PcdSerialClockRate) % (SerialBaudRate * 16)) >=3D Ser= ialBaudRate * 8) { > + Divisor++; > + } > + > + // > + // Configure baud rate > + // > + SerialPortWriteRegister (BaseAddress, R_UART_LCR, B_UART_LCR_DLAB, U= seMmio); > + SerialPortWriteRegister (BaseAddress, R_UART_BAUD_HIGH, (UINT8)(Divi= sor >> 8), UseMmio); > + SerialPortWriteRegister (BaseAddress, R_UART_BAUD_LOW, (UINT8)(Divis= or & 0xff), UseMmio); > + > + // > + // Clear DLAB and configure Data Bits, Parity, and Stop Bits. > + // Strip reserved bits from line control value > + // > + Lcr =3D (UINT8)((LcrParity << 3) | (LcrStop << 2) | LcrData); > + SerialPortWriteRegister (BaseAddress, R_UART_LCR, (UINT8)(Lcr & 0x3F= ), UseMmio); > + > + GuidHob =3D GET_NEXT_HOB (GuidHob); > + GuidHob =3D GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, Gu= idHob); > + } > + > + return RETURN_SUCCESS; > +} > diff --git a/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLi= bHob.inf > b/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.inf > new file mode 100644 > index 0000000000..ac857d3eea > --- /dev/null > +++ b/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.in= f > @@ -0,0 +1,39 @@ > +## @file > +# SerialPortLib instance for UART information retrieved from bootloader= . > +# > +# Copyright (c) 2022, Intel Corporation. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION =3D 0x00010005 > + BASE_NAME =3D BaseSerialPortLibHob > + FILE_GUID =3D d8d22930-e8ec-469f-8184-5a069149b2f= f > + MODULE_TYPE =3D BASE > + VERSION_STRING =3D 1.0 > + LIBRARY_CLASS =3D SerialPortLib > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + > +[LibraryClasses] > + PcdLib > + IoLib > + HobLib > + TimerLib > + > +[Sources] > + BaseSerialPortLibHob.c > + > +[Pcd] > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialFifoControl > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialExtendedTxFifoSize > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl > + > +[Guids] > + gUniversalPayloadSerialPortInfoGuid > -- > 2.30.2.windows.1