From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM11-BN8-obe.outbound.protection.outlook.com (NAM11-BN8-obe.outbound.protection.outlook.com [40.107.236.100]) by mx.groups.io with SMTP id smtpd.web10.37269.1679929222442253572 for ; Mon, 27 Mar 2023 08:00:23 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="no key for verify" header.i=@amperemail.onmicrosoft.com header.s=selector1-amperemail-onmicrosoft-com header.b=S58gNSvg; spf=pass (domain: os.amperecomputing.com, ip: 40.107.236.100, mailfrom: tinhnguyen@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=IUopnXtoiTBhBBWo3KQHPvzxHjWYxPr+8lPBacs2pjWdQWggYmacdJu/5+JeFgeBjhQ7/PWtU/KGICLaS/OFlGVzlug24mG+ZXYR/+wBaBjaRhdXA7JQNVpnE7NzOLKAlSwkwjBdp/CkEdI3SNLldLDV1lxZuC/THG//xXLp9bNb0ElRMf5GN/vEDN0qHjxl6NGvu8WfM1Zy0Kd/omMlpFkpouZ6eiRLVD+RMYutjTK7XeJf8UaSU6aNERcjfFKKDntZZovQ9wLPoewBiPvvjLEAXEB73Bq5V9ISGlNr/dWCWlu1Ve2acaYRnnrlfj+RmbXWM9NEC4ldbMdsBPAZcg== 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=n4hncXsrDZW3B0Evk3g4p7gNbcjD6fwGZr8cWu4Y/2w=; b=XwWvSyV7sgGRiHoNl3XHgtOP9euAuNQwUAuW/xK3fu3A81aYHROEvh2DnmIwLNWhWOl02iXwVJeUSOl7YrqmhUHbcxeR8h1GpcNeeMavLrzXgMQncOrYD+3BO6LXJhSFHzN65WIJW8Gh3vQpzlZu123EPfn9rutHhCd7nh0tJIqjqII2VghRDDO391CUK6xZMrnaiHehc6pejGrO7bi/2J/lOWFRIFvoeVhuavTE8aMxDl/iigCvORStdqZkQIJyH1tQXyHZzlgTYuKt7gLImsusXU1wo7eS3N3FZFxqlROTLLEjrCu0qaKHQ+82u21Ay4SZyMJ6f44kqxo5JaUa4g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=os.amperecomputing.com; dmarc=pass action=none header.from=amperemail.onmicrosoft.com; dkim=pass header.d=amperemail.onmicrosoft.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amperemail.onmicrosoft.com; s=selector1-amperemail-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=n4hncXsrDZW3B0Evk3g4p7gNbcjD6fwGZr8cWu4Y/2w=; b=S58gNSvgOZWwGR/4PJsi5S0N14f4gcis6K5lxzLWth2c59w5KDkdZGH2P17Hxk0iLQVqYAOAd0qvEtcvaIWxxwh+2P3I4JZBtrpLa3uV0Hyh8asA9m0GnznZgm1NH+dpmXqxczl4EH0IlzIF/vtPdSMfRsWJDoDVWlCTGJwXAbA= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=amperemail.onmicrosoft.com; Received: from MWHPR0101MB2942.prod.exchangelabs.com (2603:10b6:301:2e::14) by SN6PR0102MB3485.prod.exchangelabs.com (2603:10b6:805:f::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6178.36; Mon, 27 Mar 2023 15:00:08 +0000 Received: from MWHPR0101MB2942.prod.exchangelabs.com ([fe80::1d06:a51a:ca3d:c2f6]) by MWHPR0101MB2942.prod.exchangelabs.com ([fe80::1d06:a51a:ca3d:c2f6%4]) with mapi id 15.20.6178.041; Mon, 27 Mar 2023 15:00:08 +0000 Message-ID: <2a40d264-3446-a2b7-4a55-2f1455f4ee32@amperemail.onmicrosoft.com> Date: Mon, 27 Mar 2023 21:59:57 +0700 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.9.0 Subject: Re: [PATCH v6 1/3] UsbNetworkPkg/UsbRndis: Add USB RNDIS devices support To: =?UTF-8?B?UmljaGFyZCBIbyAo5L2V5piO5b+gKQ==?= , "devel@edk2.groups.io" CC: Andrew Fish , Leif Lindholm , Michael D Kinney , Michael Kubacki , Zhiguang Liu , Liming Gao , Rebecca Cran , Tinh Nguyen , =?UTF-8?B?VG9ueSBMbyAo576F6YeR5p2+KQ==?= References: <20230309075134.864-1-richardho@ami.com> From: "Tinh Nguyen" In-Reply-To: <20230309075134.864-1-richardho@ami.com> X-ClientProxiedBy: SI1PR02CA0015.apcprd02.prod.outlook.com (2603:1096:4:1f7::18) To MWHPR0101MB2942.prod.exchangelabs.com (2603:10b6:301:2e::14) Return-Path: tinhnguyen@os.amperecomputing.com MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: MWHPR0101MB2942:EE_|SN6PR0102MB3485:EE_ X-MS-Office365-Filtering-Correlation-Id: a2c165d1-2250-4da8-3452-08db2ed3f41c X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: zazYtVgsQzFFfqMp7OubZ/fRIqfgOzvlBeRR9dxCWrY8wYgdSf6j2bXZXgLch7Nu1r3CrRsRlHu2aid4/dlNnJClTdix+1F7xBRkP45vmtJs1OMhkjznwC7ZkKXyxOML9+E3tud8HO3NiGpFyjNI9x1T7HQoa82ssjYd2VGlspzM+GLp5LiQzarxza7vzlDmDaCwv/eCWmptM7n8Tn4My4i53Me0izLwYKhvWnmgp3Z0HZOuuaOFvXgXX1Ct9xl/lQa8F+XEEtFfPmjcnv+k2f5O3BJsh/iJwYVprLp+jMPn7XUSIPVKOz8WjiLtdFRHyhpLOcX2pjQOum+bQuZq8fOwxmfIOWlhzisQs4FzgQVaXXa1kTMpIeCRU6GKqPIuX3zuWjL8gquZzre45IURwdXkvt1TJUq3W3xfiLJQHYGFaUfKXDQt1DZe06mXuEtBOZ4yKf8l3a0AFP69juBe2/5LY7vc/D43wUd9I8/ipVibs+bq0HhKX8bSjsjOTv2/E+S4RPWp2RttuM+r5YNy6MaBFCPSWuAiXATSOn2y7gTK5ONGIi7zVlb8es9gXHVI1oMFU4dlewR0mW1oBe96ktGQNSDp0P5p/WIiYpv3ZFsmkuV5Ia5MBOfpXyW+5r50FsjaT65cVa7sCg6NVDJSaw== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:MWHPR0101MB2942.prod.exchangelabs.com;PTR:;CAT:NONE;SFS:(13230028)(4636009)(39850400004)(376002)(396003)(346002)(136003)(366004)(451199021)(8676002)(6486002)(6512007)(316002)(478600001)(26005)(4326008)(40140700001)(8936002)(31696002)(19627235002)(66476007)(6666004)(186003)(42882007)(2616005)(54906003)(66556008)(66946007)(6506007)(83170400001)(38100700002)(2906002)(31686004)(7416002)(53546011)(41300700001)(5660300002)(83380400001)(110136005)(30864003)(43740500002)(579004)(559001)(44824005);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?IQEVfWxfaMvZlNUUE4PhJzEjSO7jimKel1Oqk2plFptT4gd/h3c3eNgLV3Le?= =?us-ascii?Q?I6plfRaoqilaoBbM4Em1WTNAP9UyzR8htsnf89o8iIekpYx5e1KAcOjfns+s?= =?us-ascii?Q?TuxCieKs/CnWyxx5f/CbrxBYJRdcMuh5uUxhdSfRu9TJEw39s9BEko/wzTnx?= =?us-ascii?Q?95pQ/sjzIumqQJWx6BQk9ZuUhRm4Pti2mxym+J1ki9wldct/trNiI178EG8t?= =?us-ascii?Q?felGCYNnSdWoJzkc91PoD8Ag4elLZkfad3fNgSqiF6nIOF208PKfLlKdqhsV?= =?us-ascii?Q?ybXDPla0T1yOqygGBlIMNTQ/y/epwhTsFUnrS/YmF/7OPScV/h2dmE7NHnat?= =?us-ascii?Q?uVSSaMo2i/KiCpnIuiDvhYpVKz3meZoXKXGKIwKQKjaeHhpFGihoAocvLsku?= =?us-ascii?Q?uClETcDkNeHC98UFmtkRdaodpCbt4sEwnEFJmqoOp5TRFjuyj+oQ9jCVRMar?= =?us-ascii?Q?ilExGYBpmZnPbIQY2WysxGL8v2D5sfc0DlhZNivENx6kcABR+JiPjEDb+Jxl?= =?us-ascii?Q?hK8cCiF8kjfb93sNUhXQ1Pa85hSZ21Q+dxx+n0ZZvPGlEpg8cVj8q7OWwisz?= =?us-ascii?Q?3VtkDYRhX2EaGA2QlPGwwxI0WVymstTlQoAr1ogwaZc60EV3gs3LW1aREVIw?= =?us-ascii?Q?1BdcbNlQiGf56CRYzH4bSPRdfivJsqRW7h+fUKDuRXAjCWpsjCpPXJmUYlnI?= =?us-ascii?Q?41IJCNiaSM9v5pxU1Mkw6/WwKvygLgFkX78Bez5cSXOtshtoZAetCcL7lDQA?= =?us-ascii?Q?/UmXmlrjEd6QBhE6lq2z6AQ9Ka44Py5uGkJtHLFuHHCvw+7RZ6sLdaptu1oe?= =?us-ascii?Q?cSDNmotqjsDAUHnNr08dBEE033nj9QK1prgdhHawpFZeDUgzLKMpUIjWH15F?= =?us-ascii?Q?N45n59YgjycfJZEZ/oGIDwYorKdQQr8638F9iGGKSrz7eF1HdsNM79QJ5rdm?= =?us-ascii?Q?ig1Zj2WbVyJH7kAc7zJqYY/e/SADTnh9GGEy2ZW9GEUg4F04rZaOs081/dDf?= =?us-ascii?Q?Uor+2YsOfK3LD8NBpYVx1SkMy1/7K+npqlObwJwARcp7mlZfWQy7KKZgcVPb?= =?us-ascii?Q?nX1wWTf5fdD8182OJFy9oC1KDHjO88f+gi+u95jGNvxGsM4HR1B1C6oAOVd/?= =?us-ascii?Q?eXi2Ablos9mMOZPhaS9a7FNl5B4YIf/891iQDbbdZHx11y/TnLi+3t92Ppt1?= =?us-ascii?Q?RJ9/eUs4keg0biZP9My9nsXNBW11FYhc0R8LqlIC6VBipuPMlvPlqagbOGj2?= =?us-ascii?Q?U/aeY/clM9R6EfPEnzzV/iFo+fyql8UzvcmDormASYhaVV7RcPjk2wK6sqZp?= =?us-ascii?Q?ekri7MeQ+3BVMyu7ycX5A6rOn3SId8ZdU4Pm64DntLOxhkSIqbDTiUb64BTH?= =?us-ascii?Q?rEaLalLHCglGV65QhlT/e2jszaN3ewV53u+kFWVaZuFM7UlBS0BsQFq8REN7?= =?us-ascii?Q?OTLX9RK+byKvw2C+I9KaxYeXJbx0SqIRxBx3eRRY4Wl78ULl8SywgtVqUKAY?= =?us-ascii?Q?LjBF3CHoAkN3E3aIKR0epItmKUDQGjeZBykK4JE0l+rqJEbXYhY/wN7HSH48?= =?us-ascii?Q?NoBf7CK3J00KKIJ5Tlg9Z55xnGpwuVvQ7bTdLmDQIEtw+ctcpxs5mJ5gvjZZ?= =?us-ascii?Q?coSZ8Mg22xfFWKkjVSUNW/M=3D?= X-OriginatorOrg: amperemail.onmicrosoft.com X-MS-Exchange-CrossTenant-Network-Message-Id: a2c165d1-2250-4da8-3452-08db2ed3f41c X-MS-Exchange-CrossTenant-AuthSource: MWHPR0101MB2942.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Mar 2023 15:00:07.9491 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3bc2b170-fd94-476d-b0ce-4229bdc904a7 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: JC8UnhAaMoMezlJm/VKAASM8mHHSTF5ilMAV29QPFbvMLTI1N378YbyS61gxTMGHJSq3ZBiiOC4GFX8ysk/HN38/vKg9icuD5mT5HqEE6qFslVGmAVbTGyrqIBu02fhG X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR0102MB3485 Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable Are there any plans for these patches? Could someone please assist in=20 reviewing these? On 3/9/2023 2:51 PM, Richard Ho (=E4=BD=95=E6=98=8E=E5=BF=A0) wrote: > This driver provides UEFI driver for USB RNDIS device > > Signed-off-by: Richard Ho > Cc: Andrew Fish > Cc: Leif Lindholm > Cc: Michael D Kinney > Cc: Michael Kubacki > Cc: Zhiguang Liu > Cc: Liming Gao > Cc: Rebecca Cran > Tested-by: Tinh Nguyen > Reviewed-by: Tony Lo > --- > UsbNetworkPkg/UsbNetworkPkg.dec | 46 + > UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc | 9 + > .../Config/UsbNetworkPkgComponentsDxe.inc.dsc | 20 + > .../Config/UsbNetworkPkgDefines.inc.dsc | 23 + > .../Config/UsbNetworkPkgComponentsDxe.inc.fdf | 20 + > UsbNetworkPkg/NetworkCommon/NetworkCommon.inf | 49 + > UsbNetworkPkg/UsbRndis/UsbRndis.inf | 42 + > .../Protocol/EdkIIUsbEthernetProtocol.h | 878 ++++++++ > UsbNetworkPkg/NetworkCommon/DriverBinding.h | 266 +++ > UsbNetworkPkg/UsbRndis/UsbRndis.h | 586 ++++++ > UsbNetworkPkg/NetworkCommon/ComponentName.c | 263 +++ > UsbNetworkPkg/NetworkCommon/DriverBinding.c | 595 ++++++ > UsbNetworkPkg/NetworkCommon/PxeFunction.c | 1803 +++++++++++++++++ > UsbNetworkPkg/UsbRndis/ComponentName.c | 172 ++ > UsbNetworkPkg/UsbRndis/UsbRndis.c | 886 ++++++++ > UsbNetworkPkg/UsbRndis/UsbRndisFunction.c | 1718 ++++++++++++++++ > UsbNetworkPkg/ReadMe.md | 65 + > UsbNetworkPkg/ReleaseNotes.md | 11 + > 18 files changed, 7452 insertions(+) > create mode 100644 UsbNetworkPkg/UsbNetworkPkg.dec > create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc > create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.= dsc > create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc > create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.= fdf > create mode 100644 UsbNetworkPkg/NetworkCommon/NetworkCommon.inf > create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.inf > create mode 100644 UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProto= col.h > create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.h > create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.h > create mode 100644 UsbNetworkPkg/NetworkCommon/ComponentName.c > create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.c > create mode 100644 UsbNetworkPkg/NetworkCommon/PxeFunction.c > create mode 100644 UsbNetworkPkg/UsbRndis/ComponentName.c > create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.c > create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndisFunction.c > create mode 100644 UsbNetworkPkg/ReadMe.md > create mode 100644 UsbNetworkPkg/ReleaseNotes.md > > diff --git a/UsbNetworkPkg/UsbNetworkPkg.dec b/UsbNetworkPkg/UsbNetworkPk= g.dec > new file mode 100644 > index 000000000000..30e4e4c8aac7 > --- /dev/null > +++ b/UsbNetworkPkg/UsbNetworkPkg.dec > @@ -0,0 +1,46 @@ > +## @file > +# This package defines Usb network specific interfaces and library clas= ses > +# as well as configuration for standard edk2 packages. > +# > +# Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > + DEC_SPECIFICATION =3D 0x00010005 > + PACKAGE_NAME =3D UsbNetworkPkg > + PACKAGE_GUID =3D abfab91e-37ea-4cb4-80a6-563dbb0bcec= 6 > + PACKAGE_VERSION =3D 0.1 > + > +[Includes] > + Include > + > +[Protocols] > + ## Include/Protocol/EdkIIUsbEthernet.h > + gEdkIIUsbEthProtocolGuid =3D { 0x8d8969cc, 0xfeb0, 0x4303, { 0xb2, 0x1= a, 0x1f, 0x11, 0x6f, 0x38, 0x56, 0x43 } } > + > +[Guids] > + ## Usb Network package token space GUID > + gUsbNetworkPkgTokenSpaceGuid =3D { 0xA1231E82, 0x21B8, 0x4204, { 0x92= , 0xBB, 0x37, 0x3A, 0xFB, 0x01, 0xC6, 0xA1 } } > + > +[PcdsFeatureFlag] > + > + ## Set the PCD 'UsbCdcEcmSupport' to 'TRUE' if 'Usb Cdc Ecm device' ne= ed to be enabled. > + gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport|FALSE|BOOLEAN|0x00000001 > + > + ## Set the PCD 'UsbCdcNcmSupport' to 'TRUE' if 'Usb Cdc Ncm device' ne= ed to be enabled. > + gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE|BOOLEAN|0x00000002 > + > + ## Set the PCD 'UsbRndisSupport' to 'TRUE' if 'Usb Rndis device' need = to be enabled. > + gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE|BOOLEAN|0x00000003 > + > +[PcdsFixedAtBuild, PcdsPatchableInModule] > + ## Support rate limiting > + gUsbNetworkPkgTokenSpaceGuid.EnableRateLimiting|FALSE|BOOLEAN|0x000100= 01 > + > + ## The rate limiting Credit value is check in rate limiter event. > + # It is to control the RateLimitingCreditCount max value. > + gUsbNetworkPkgTokenSpaceGuid.RateLimitingCredit|10|UINT32|0x00010002 > + > + ## The value of rate limiter event for timeout check. Default value is= 100(unit 1ms). > + gUsbNetworkPkgTokenSpaceGuid.RateLimitingFactor|100|UINT32|0x00010003 > diff --git a/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc b/UsbNetworkPkg/C= onfig/UsbNetworkPkg.inc.dsc > new file mode 100644 > index 000000000000..a3316b1d4a89 > --- /dev/null > +++ b/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc > @@ -0,0 +1,9 @@ > +## @file > +# Global DSC definitions to be included into project DSC file. > +# > +# Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Components.X64] > +!include UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc > diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc b/Us= bNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc > new file mode 100644 > index 000000000000..544df8404c64 > --- /dev/null > +++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc > @@ -0,0 +1,20 @@ > +## @file > +# List of Core Components. > +# > +# Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > + UsbNetworkPkg/NetworkCommon/NetworkCommon.inf > + > +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport > + UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf > +!endif > + > +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport > + UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf > +!endif > + > +!if gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport > + UsbNetworkPkg/UsbRndis/UsbRndis.inf > +!endif > diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc b/UsbNetwo= rkPkg/Config/UsbNetworkPkgDefines.inc.dsc > new file mode 100644 > index 000000000000..85a309bcf567 > --- /dev/null > +++ b/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc > @@ -0,0 +1,23 @@ > +## @file > +# Global switches enable/disable project features. > +# > +# Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > +!if "IA32" in $(ARCH) && "X64" in $(ARCH) > + DEFINE PEI=3DIA32 > + DEFINE DXE=3DX64 > +!else > + DEFINE PEI=3DCOMMON > + DEFINE DXE=3DCOMMON > +!endif > + > +[Packages] > + UsbNetworkPkg/UsbNetworkPkg.dec > + > +[PcdsFeatureFlag] > + gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport|FALSE > + gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE > + gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE > diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf b/Us= bNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf > new file mode 100644 > index 000000000000..10616d97edb4 > --- /dev/null > +++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf > @@ -0,0 +1,20 @@ > +## @file > +# List of Core Components. > +# > +# Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > + INF UsbNetworkPkg/NetworkCommon/NetworkCommon.inf > + > +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport > + INF UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf > +!endif > + > +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport > + INF UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf > +!endif > + > +!if gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport > + INF UsbNetworkPkg/UsbRndis/UsbRndis.inf > +!endif > diff --git a/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf b/UsbNetworkPk= g/NetworkCommon/NetworkCommon.inf > new file mode 100644 > index 000000000000..8923102bc350 > --- /dev/null > +++ b/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf > @@ -0,0 +1,49 @@ > +## @file > +# This is Usb Network Common driver for DXE phase. > +# > +# Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > + INF_VERSION =3D 0x00010005 > + BASE_NAME =3D NetworkCommon > + FILE_GUID =3D ca6eb4f4-f1d6-4375-97d6-18856871e1b= f > + MODULE_TYPE =3D DXE_DRIVER > + VERSION_STRING =3D 1.0 > + ENTRY_POINT =3D NetworkCommonEntry > + > +[Sources] > + DriverBinding.c > + DriverBinding.h > + ComponentName.c > + PxeFunction.c > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + UsbNetworkPkg/UsbNetworkPkg.dec > + > +[LibraryClasses] > + UefiDriverEntryPoint > + UefiBootServicesTableLib > + UefiLib > + DebugLib > + UefiUsbLib > + MemoryAllocationLib > + BaseMemoryLib > + > +[Protocols] > + gEfiNetworkInterfaceIdentifierProtocolGuid_31 > + gEfiUsbIoProtocolGuid > + gEfiDevicePathProtocolGuid > + gEfiDriverBindingProtocolGuid > + gEdkIIUsbEthProtocolGuid > + > +[Pcd] > + gUsbNetworkPkgTokenSpaceGuid.EnableRateLimiting > + gUsbNetworkPkgTokenSpaceGuid.RateLimitingCredit > + gUsbNetworkPkgTokenSpaceGuid.RateLimitingFactor > + > +[Depex] > + TRUE > diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.inf b/UsbNetworkPkg/UsbRndis= /UsbRndis.inf > new file mode 100644 > index 000000000000..64205e427745 > --- /dev/null > +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.inf > @@ -0,0 +1,42 @@ > +## @file > +# This is Usb Rndis driver for DXE phase. > +# > +# Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > + INF_VERSION =3D 0x00010005 > + BASE_NAME =3D UsbRndis > + FILE_GUID =3D 11E32C34-60B5-4991-8DEA-63D3E8C876D= E > + MODULE_TYPE =3D DXE_DRIVER > + VERSION_STRING =3D 1.0 > + ENTRY_POINT =3D UsbRndisEntry > + > +[Sources] > + UsbRndis.c > + UsbRndis.h > + UsbRndisFunction.c > + ComponentName.c > + > +[Packages] > + MdePkg/MdePkg.dec > + UsbNetworkPkg/UsbNetworkPkg.dec > + > +[LibraryClasses] > + UefiDriverEntryPoint > + UefiBootServicesTableLib > + UefiLib > + DebugLib > + UefiUsbLib > + MemoryAllocationLib > + BaseMemoryLib > + > +[Protocols] > + gEfiUsbIoProtocolGuid > + gEfiDevicePathProtocolGuid > + gEfiDriverBindingProtocolGuid > + gEdkIIUsbEthProtocolGuid > + > +[Depex] > + TRUE > diff --git a/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h b/= UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h > new file mode 100644 > index 000000000000..f54946c7aa69 > --- /dev/null > +++ b/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h > @@ -0,0 +1,878 @@ > +/** @file > + Header file contains code for USB Ethernet Protocol > + definitions > + > + Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#ifndef EDKII_USB_ETHERNET_PROTOCOL_H_ > +#define EDKII_USB_ETHERNET_PROTOCOL_H_ > + > +#define EDKII_USB_ETHERNET_PROTOCOL_GUID \ > + {0x8d8969cc, 0xfeb0, 0x4303, {0xb2, 0x1a, 0x1f, 0x11, 0x6f, 0x38, 0x= 56, 0x43}} > + > +typedef struct _EDKII_USB_ETHERNET_PROTOCOL EDKII_USB_ETHERNET_PROTOCOL; > + > +#define USB_CDC_CLASS 0x02 > +#define USB_CDC_ACM_SUBCLASS 0x02 > +#define USB_CDC_ECM_SUBCLASS 0x06 > +#define USB_CDC_NCM_SUBCLASS 0x0D > +#define USB_CDC_DATA_CLASS 0x0A > +#define USB_CDC_DATA_SUBCLASS 0x00 > +#define USB_NO_CLASS_PROTOCOL 0x00 > +#define USB_NCM_NTB_PROTOCOL 0x01 > +#define USB_VENDOR_PROTOCOL 0xFF > + > +// Type Values for the DescriptorType Field > +#define CS_INTERFACE 0x24 > +#define CS_ENDPOINT 0x25 > + > +// Descriptor SubType in Functional Descriptors > +#define HEADER_FUN_DESCRIPTOR 0x00 > +#define UNION_FUN_DESCRIPTOR 0x06 > +#define ETHERNET_FUN_DESCRIPTOR 0x0F > + > +#define MAX_LAN_INTERFACE 0x10 > + > +// Table 20: Class-Specific Notification Codes > +#define USB_CDC_NETWORK_CONNECTION 0x00 > + > +// 6.3.1 NetworkConnection > +#define NETWORK_CONNECTED 0x01 > +#define NETWORK_DISCONNECT 0x00 > + > +// USB Header functional Descriptor > +typedef struct { > + UINT8 FunctionLength; > + UINT8 DescriptorType; > + UINT8 DescriptorSubtype; > + UINT16 BcdCdc; > +} USB_HEADER_FUN_DESCRIPTOR; > + > +// USB Union Functional Descriptor > +typedef struct { > + UINT8 FunctionLength; > + UINT8 DescriptorType; > + UINT8 DescriptorSubtype; > + UINT8 MasterInterface; > + UINT8 SlaveInterface; > +} USB_UNION_FUN_DESCRIPTOR; > + > +// USB Ethernet Functional Descriptor > +typedef struct { > + UINT8 FunctionLength; > + UINT8 DescriptorType; > + UINT8 DescriptorSubtype; > + UINT8 MacAddress; > + UINT32 EthernetStatistics; > + UINT16 MaxSegmentSize; > + UINT16 NumberMcFilters; > + UINT8 NumberPowerFilters; > +} USB_ETHERNET_FUN_DESCRIPTOR; > + > +typedef struct { > + UINT32 UsBitRate; > + UINT32 DsBitRate; > +} USB_CONNECT_SPEED_CHANGE; > + > +// Request Type Codes for USB Ethernet > +#define USB_ETHERNET_GET_REQ_TYPE 0xA1 > +#define USB_ETHERNET_SET_REQ_TYPE 0x21 > + > +// Class-Specific Request Codes for Ethernet subclass > +// USB ECM 1.2 specification, Section 6.2 > +#define SET_ETH_MULTICAST_FILTERS_REQ 0x40 > +#define SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ 0x41 > +#define GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ 0x42 > +#define SET_ETH_PACKET_FILTER_REQ 0x43 > +#define GET_ETH_STATISTIC_REQ 0x44 > + > +// USB ECM command request length > +#define USB_ETH_POWER_FILTER_LENGTH 2 // Section 6.2.3 > +#define USB_ETH_PACKET_FILTER_LENGTH 0 // Section 6.2.4 > +#define USB_ETH_STATISTIC 4 // Section 6.2.5 > + > +// USB Ethernet Packet Filter Bitmap > +// USB ECM 1.2 specification, Section 6.2.4 > +#define USB_ETH_PACKET_TYPE_PROMISCUOUS BIT0 > +#define USB_ETH_PACKET_TYPE_ALL_MULTICAST BIT1 > +#define USB_ETH_PACKET_TYPE_DIRECTED BIT2 > +#define USB_ETH_PACKET_TYPE_BROADCAST BIT3 > +#define USB_ETH_PACKET_TYPE_MULTICAST BIT4 > + > +// USB Ethernet Statistics Feature Selector Codes > +// USB ECM 1.2 specification, Section 6.2.5 > +#define USB_ETH_XMIT_OK 0x01 > +#define USB_ETH_RCV_OK 0x02 > +#define USB_ETH_XMIT_ERROR 0x03 > +#define USB_ETH_RCV_ERROR 0x04 > +#define USB_ETH_RCV_NO_BUFFER 0x05 > +#define USB_ETH_DIRECTED_BYTES_XMIT 0x06 > +#define USB_ETH_DIRECTED_FRAMES_XMIT 0x07 > +#define USB_ETH_MULTICAST_BYTES_XMIT 0x08 > +#define USB_ETH_MULTICAST_FRAMES_XMIT 0x09 > +#define USB_ETH_BROADCAST_BYTES_XMIT 0x0A > +#define USB_ETH_BROADCAST_FRAMES_XMIT 0x0B > +#define USB_ETH_DIRECTED_BYTES_RCV 0x0C > +#define USB_ETH_DIRECTED_FRAMES_RCV 0x0D > +#define USB_ETH_MULTICAST_BYTES_RCV 0x0E > +#define USB_ETH_MULTICAST_FRAMES_RCV 0x0F > +#define USB_ETH_BROADCAST_BYTES_RCV 0x10 > +#define USB_ETH_BROADCAST_FRAMES_RCV 0x11 > +#define USB_ETH_RCV_CRC_ERROR 0x12 > +#define USB_ETH_TRANSMIT_QUEUE_LENGTH 0x13 > +#define USB_ETH_RCV_ERROR_ALIGNMENT 0x14 > +#define USB_ETH_XMIT_ONE_COLLISION 0x15 > +#define USB_ETH_XMIT_MORE_COLLISIONS 0x16 > +#define USB_ETH_XMIT_DEFERRED 0x17 > +#define USB_ETH_XMIT_MAX_COLLISIONS 0x18 > +#define USB_ETH_RCV_OVERRUN 0x19 > +#define USB_ETH_XMIT_UNDERRUN 0x1A > +#define USB_ETH_XMIT_HEARTBEAT_FAILURE 0x1B > +#define USB_ETH_XMIT_TIMES_CRS_LOST 0x1C > +#define USB_ETH_XMIT_LATE_COLLISIONS 0x1D > + > +// NIC Information > +typedef struct { > + UINT32 Signature; > + EDKII_USB_ETHERNET_PROTOCOL *UsbEth; > + UINT16 InterrupOpFlag; > + UINT64 MappedAddr; > + PXE_MAC_ADDR McastList[MAX_MCAST_ADDRESS_CNT]; > + UINT8 McastCount; > + UINT64 MediaHeader[MAX_XMIT_BUFFERS]; > + UINT8 TxBufferCount; > + UINT16 State; > + BOOLEAN CanTransmit; > + UINT16 ReceiveStatus; > + UINT8 RxFilter; > + UINT32 RxFrame; > + UINT32 TxFrame; > + UINT16 NetworkConnect; > + UINT8 CableDetect; > + UINT16 MaxSegmentSize; > + EFI_MAC_ADDRESS MacAddr; > + PXE_CPB_START_31 PxeStart; > + PXE_CPB_INITIALIZE PxeInit; > + UINT8 PermNodeAddress[PXE_MAC_LENGTH]; > + UINT8 CurrentNodeAddress[PXE_MAC_LENGTH]; > + UINT8 BroadcastNodeAddress[PXE_MAC_LENGTH]; > + EFI_USB_DEVICE_REQUEST Request; > + EFI_EVENT RateLimiter; > + UINT32 RateLimitingCredit; > + UINT32 RateLimitingCreditCount; > + UINT32 RateLimitingPollTimer; > + BOOLEAN RateLimitingEnable; > +} NIC_DATA; > + > +#define NIC_DATA_SIGNATURE SIGNATURE_32('n', 'i', 'c', 'd') > +#define NIC_DATA_FROM_EDKII_USB_ETHERNET_PROTOCOL(a) CR (a, NIC_DATA, U= sbEth, NIC_DATA_SIGNATURE) > + > +/** > + This command is used to determine the operational state of the UNDI. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_GET_STATE)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + This command is used to change the UNDI operational state from stopped= to started. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_START)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + This command is used to change the UNDI operational state from started= to stopped. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_STOP)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + This command is used to retrieve initialization information that is > + needed by drivers and applications to initialized UNDI. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_GET_INIT_INFO)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + This command is used to retrieve configuration information about > + the NIC being controlled by the UNDI. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_GET_CONFIG_INFO)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + This command resets the network adapter and initializes UNDI using > + the parameters supplied in the CPB. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_INITIALIZE)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + This command resets the network adapter and reinitializes the UNDI > + with the same parameters provided in the Initialize command. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_RESET)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + The Shutdown command resets the network adapter and leaves it in a > + safe state for another driver to initialize. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_SHUTDOWN)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + The Interrupt Enables command can be used to read and/or change > + the current external interrupt enable settings. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_INTERRUPT_ENABLE)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + This command is used to read and change receive filters and, > + if supported, read and change the multicast MAC address filter list. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_RECEIVE_FILTER)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + This command is used to get current station and broadcast MAC addresse= s > + and, if supported, to change the current station MAC address. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_STATION_ADDRESS)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + This command is used to read and clear the NIC traffic statistics. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_STATISTICS)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + Translate a multicast IPv4 or IPv6 address to a multicast MAC address. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_MCAST_IPTOMAC)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + This command is used to read and write (if supported by NIC H/W) > + nonvolatile storage on the NIC. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_NV_DATA)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + This command returns the current interrupt status and/or the > + transmitted buffer addresses and the current media status. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_GET_STATUS)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + This command is used to fill the media header(s) in transmit packet(s)= . > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_FILL_HEADER)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + The Transmit command is used to place a packet into the transmit queue= . > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_TRANSMIT)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + When the network adapter has received a frame, this command is used > + to copy the frame into driver/application storage. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_UNDI_RECEIVE)( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +/** > + This command resets the network adapter and initializes UNDI using > + the parameters supplied in the CPB. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in, out] Nic A pointer to the Network interface controller dat= a. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_INITIALIZE)( > + IN PXE_CDB *Cdb, > + IN OUT NIC_DATA *Nic > + ); > + > +/** > + This command is used to read and clear the NIC traffic statistics. > + > + @param[in] Nic A pointer to the Network interface controller data= . > + @param[in] DbAddr Data Block Address. > + @param[in] DbSize Data Block Size. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_STATISTICS)( > + IN NIC_DATA *Nic, > + IN UINT64 DbAddr, > + IN UINT16 DbSize > + ); > + > +/** > + This function is used to manage a USB device with the bulk transfer pi= pe. The endpoint is Bulk in. > + > + @param[in] Cdb A pointer to the command descriptor bloc= k. > + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROT= OCOL instance. > + @param[in, out] Packet A pointer to the buffer of data that wil= l be transmitted to USB > + device or received from USB device. > + @param[in, out] PacketLength A pointer to the PacketLength. > + > + @retval EFI_SUCCESS The bulk transfer has been successfully = executed. > + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status= is returned in status. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due t= o a lack of resources. > + @retval EFI_TIMEOUT The control transfer fails due to timeou= t. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_RECEIVE)( > + IN PXE_CDB *Cdb, > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN OUT VOID *Packet, > + IN OUT UINTN *PacketLength > + ); > + > +/** > + This function is used to manage a USB device with the bulk transfer pi= pe. The endpoint is Bulk out. > + > + @param[in] Cdb A pointer to the command descriptor bloc= k. > + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROT= OCOL instance. > + @param[in, out] Packet A pointer to the buffer of data that wil= l be transmitted to USB > + device or received from USB device. > + @param[in, out] PacketLength A pointer to the PacketLength. > + > + @retval EFI_SUCCESS The bulk transfer has been successfully = executed. > + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status= is returned in status. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due t= o a lack of resources. > + @retval EFI_TIMEOUT The control transfer fails due to timeou= t. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_TRANSMIT)( > + IN PXE_CDB *Cdb, > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN OUT VOID *Packet, > + IN OUT UINTN *PacketLength > + ); > + > +/** > + This function is used to manage a USB device with an interrupt transfe= r pipe. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROT= OCOL instance. > + @param[in] IsNewTransfer If TRUE, a new transfer will be submitte= d to USB controller. If > + FALSE, the interrupt transfer is deleted= from the device's interrupt > + transfer queue. > + @param[in] PollingInterval Indicates the periodic rate, in millisec= onds, that the transfer is to be > + executed.This parameter is required when= IsNewTransfer is TRUE. The > + value must be between 1 to 255, otherwis= e EFI_INVALID_PARAMETER is returned. > + The units are in milliseconds. > + @param[in] Request A pointer to the EFI_USB_DEVICE_REQUEST = data. > + > + @retval EFI_SUCCESS The asynchronous USB transfer request tr= ansfer has been successfully executed. > + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request fa= iled. > + > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_INTERRUPT)( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN BOOLEAN IsNewTransfer, > + IN UINTN PollingInterval, > + IN EFI_USB_DEVICE_REQUEST *Request > + ); > + > +/** > + Retrieves the USB Ethernet Mac Address. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOCOL= instance. > + @param[out] MacAddress A pointer to the caller allocated USB Ethern= et Mac Address. > + > + @retval EFI_SUCCESS The USB Header Functional descriptor was= retrieved successfully. > + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. > + @retval EFI_NOT_FOUND The USB Header Functional descriptor was= not found. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_GET_ETH_MAC_ADDRESS)( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT EFI_MAC_ADDRESS *MacAddress > + ); > + > +/** > + Retrieves the USB Ethernet Bulk transfer data size. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOCOL= instance. > + @param[out] BulkSize A pointer to the Bulk transfer data size. > + > + @retval EFI_SUCCESS The USB Header Functional descriptor was= retrieved successfully. > + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. > + @retval EFI_NOT_FOUND The USB Header Functional descriptor was= not found. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETH_MAX_BULK_SIZE)( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT UINTN *BulkSize > + ); > + > +/** > + Retrieves the USB Header functional Descriptor. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET= _PROTOCOL instance. > + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated U= SB Header Functional Descriptor. > + > + @retval EFI_SUCCESS The USB Header Functional descriptor was= retrieved successfully. > + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. > + @retval EFI_NOT_FOUND The USB Header Functional descriptor was= not found. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_HEADER_FUNCTIONAL_DESCRIPTOR)( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor > + ); > + > +/** > + Retrieves the USB Union functional Descriptor. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET= _PROTOCOL instance. > + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated U= SB Union Functional Descriptor. > + > + @retval EFI_SUCCESS The USB Union Functional descriptor was = retrieved successfully. > + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. > + @retval EFI_NOT_FOUND The USB Union Functional descriptor was = not found. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_UNION_FUNCTIONAL_DESCRIPTOR)( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor > + ); > + > +/** > + Retrieves the USB Ethernet functional Descriptor. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET= _PROTOCOL instance. > + @param[out] UsbEthFunDescriptor A pointer to the caller allocated U= SB Ethernet Functional Descriptor. > + > + @retval EFI_SUCCESS The USB Ethernet Functional descriptor w= as retrieved successfully. > + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL. > + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor w= as not found. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_FUNCTIONAL_DESCRIPTOR)( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor > + ); > + > +/** > + This request sets the Ethernet device multicast filters as specified i= n the > + sequential list of 48 bit Ethernet multicast addresses. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET= _PROTOCOL instance. > + @param[in] Value Number of filters. > + @param[in] McastAddr A pointer to the value of the multi= cast addresses. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_SET_ETH_MULTICAST_FILTERS)( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 Value, > + IN VOID *McastAddr > + ); > + > +/** > + This request sets up the specified Ethernet power management pattern f= ilter as > + described in the data structure. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET= _PROTOCOL instance. > + @param[in] Value Number of filters. > + @param[in] Length Size of the power management patter= n filter data. > + @param[in] PatternFilter A pointer to the power management p= attern filter structure. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER)( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 Value, > + IN UINT16 Length, > + IN VOID *PatternFilter > + ); > + > +/** > + This request retrieves the status of the specified Ethernet power mana= gement > + pattern filter from the device. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET= _PROTOCOL instance. > + @param[in] Value The filter number. > + @param[out] PatternActive A pointer to the pattern active boo= lean. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER)( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 Value, > + OUT BOOLEAN *PatternActive > + ); > + > +/** > + This request is used to configure device Ethernet packet filter settin= gs. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROT= OCOL instance. > + @param[in] Value Packet Filter Bitmap. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_SET_ETH_PACKET_FILTER)( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 Value > + ); > + > +/** > + This request is used to retrieve a statistic based on the feature sele= ctor. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET_= PROTOCOL instance. > + @param[in] FeatureSelector Value of the feature selector. > + @param[out] Statistic A pointer to the 32 bit unsigned int= eger. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_USB_ETHERNET_GET_ETH_STATISTIC)( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 FeatureSelector, > + OUT VOID *Statistic > + ); > + > +typedef struct { > + EDKII_USB_ETHERNET_UNDI_GET_STATE UsbEthUndiGetState; > + EDKII_USB_ETHERNET_UNDI_START UsbEthUndiStart; > + EDKII_USB_ETHERNET_UNDI_STOP UsbEthUndiStop; > + EDKII_USB_ETHERNET_UNDI_GET_INIT_INFO UsbEthUndiGetInitInfo; > + EDKII_USB_ETHERNET_UNDI_GET_CONFIG_INFO UsbEthUndiGetConfigInfo; > + EDKII_USB_ETHERNET_UNDI_INITIALIZE UsbEthUndiInitialize; > + EDKII_USB_ETHERNET_UNDI_RESET UsbEthUndiReset; > + EDKII_USB_ETHERNET_UNDI_SHUTDOWN UsbEthUndiShutdown; > + EDKII_USB_ETHERNET_UNDI_INTERRUPT_ENABLE UsbEthUndiInterruptEnable; > + EDKII_USB_ETHERNET_UNDI_RECEIVE_FILTER UsbEthUndiReceiveFilter; > + EDKII_USB_ETHERNET_UNDI_STATION_ADDRESS UsbEthUndiStationAddress; > + EDKII_USB_ETHERNET_UNDI_STATISTICS UsbEthUndiStatistics; > + EDKII_USB_ETHERNET_UNDI_MCAST_IPTOMAC UsbEthUndiMcastIp2Mac; > + EDKII_USB_ETHERNET_UNDI_NV_DATA UsbEthUndiNvData; > + EDKII_USB_ETHERNET_UNDI_GET_STATUS UsbEthUndiGetStatus; > + EDKII_USB_ETHERNET_UNDI_FILL_HEADER UsbEthUndiFillHeader; > + EDKII_USB_ETHERNET_UNDI_TRANSMIT UsbEthUndiTransmit; > + EDKII_USB_ETHERNET_UNDI_RECEIVE UsbEthUndiReceive; > +} EDKII_USB_ETHERNET_UNDI; > + > +// The EDKII_USB_ETHERNET_PROTOCOL provides some basic USB Ethernet devi= ce relevant > +// descriptor and specific requests. > +struct _EDKII_USB_ETHERNET_PROTOCOL { > + EDKII_USB_ETHERNET_UNDI UsbEthUndi; > + // for calling the UNDI child functions > + EDKII_USB_ETHERNET_INITIALIZE UsbEthInitia= lize; > + EDKII_USB_ETHERNET_STATISTICS UsbEthStatis= tics; > + EDKII_USB_ETHERNET_RECEIVE UsbEthReceiv= e; > + EDKII_USB_ETHERNET_TRANSMIT UsbEthTransm= it; > + EDKII_USB_ETHERNET_INTERRUPT UsbEthInterr= upt; > + EDKII_USB_GET_ETH_MAC_ADDRESS UsbEthMacAdd= ress; > + EDKII_USB_ETH_MAX_BULK_SIZE UsbEthMaxBul= kSize; > + EDKII_USB_HEADER_FUNCTIONAL_DESCRIPTOR UsbHeaderFun= Descriptor; > + EDKII_USB_UNION_FUNCTIONAL_DESCRIPTOR UsbUnionFunD= escriptor; > + EDKII_USB_ETHERNET_FUNCTIONAL_DESCRIPTOR UsbEthFunDes= criptor; > + EDKII_USB_ETHERNET_SET_ETH_MULTICAST_FILTERS SetUsbEthMca= stFilter; > + EDKII_USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER SetUsbEthPow= erPatternFilter; > + EDKII_USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER GetUsbEthPow= erPatternFilter; > + EDKII_USB_ETHERNET_SET_ETH_PACKET_FILTER SetUsbEthPac= ketFilter; > + EDKII_USB_ETHERNET_GET_ETH_STATISTIC GetUsbEthSta= tistic; > +}; > + > +extern EFI_GUID gEdkIIUsbEthProtocolGuid; > + > +#endif > diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.h b/UsbNetworkPkg/= NetworkCommon/DriverBinding.h > new file mode 100644 > index 000000000000..0416ce132302 > --- /dev/null > +++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.h > @@ -0,0 +1,266 @@ > +/** @file > + Header file for for USB network common driver > + > + Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#ifndef _DRIVER_BINDING_H_ > +#define _DRIVER_BINDING_H_ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define NETWORK_COMMON_DRIVER_VERSION 1 > +#define NETWORK_COMMON_POLLING_INTERVAL 0x10 > +#define RX_BUFFER_COUNT 32 > +#define TX_BUFFER_COUNT 32 > +#define MEMORY_REQUIRE 0 > + > +#define UNDI_DEV_SIGNATURE SIGNATURE_32('u','n','d','i') > +#define UNDI_DEV_FROM_THIS(a) CR(a, NIC_DEVICE, NiiProtocol, UNDI_DEV_S= IGNATURE) > +#define UNDI_DEV_FROM_NIC(a) CR(a, NIC_DEVICE, NicInfo, UNDI_DEV_SIGNA= TURE) > + > +#pragma pack(1) > +typedef struct { > + UINT8 DestAddr[PXE_HWADDR_LEN_ETHER]; > + UINT8 SrcAddr[PXE_HWADDR_LEN_ETHER]; > + UINT16 Protocol; > +} EthernetHeader; > +#pragma pack() > + > +typedef struct { > + UINTN Signature; > + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL NiiProtocol; > + EFI_HANDLE DeviceHandle; > + EFI_DEVICE_PATH_PROTOCOL *BaseDevPath; > + EFI_DEVICE_PATH_PROTOCOL *DevPath; > + NIC_DATA NicInfo; > + VOID *ReceiveBuffer; > +} NIC_DEVICE; > + > +typedef VOID (*API_FUNC)( > + PXE_CDB *, > + NIC_DATA * > + ); > + > +extern PXE_SW_UNDI *gPxe; > +extern NIC_DEVICE *gLanDeviceList[MAX_LAN_INTERFACE]; > +extern EFI_COMPONENT_NAME2_PROTOCOL gNetworkCommonComponentName2; > + > +EFI_STATUS > +EFIAPI > +NetworkCommonSupported ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > + ); > + > +EFI_STATUS > +EFIAPI > +NetworkCommonDriverStart ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > + ); > + > +EFI_STATUS > +EFIAPI > +NetworkCommonDriverStop ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN UINTN NumberOfChildren, > + IN EFI_HANDLE *ChildHandleBuffer > + ); > + > +VOID > +PxeStructInit ( > + OUT PXE_SW_UNDI *PxeSw > + ); > + > +VOID > +UpdateNicNum ( > + IN NIC_DATA *Nic, > + IN OUT PXE_SW_UNDI *PxeSw > + ); > + > +EFI_STATUS > +EFIAPI > +UndiApiEntry ( > + IN UINT64 Cdb > + ); > + > +UINTN > +MapIt ( > + IN NIC_DATA *Nic, > + IN UINT64 MemAddr, > + IN UINT32 Size, > + IN UINT32 Direction, > + OUT UINT64 MappedAddr > + ); > + > +VOID > +UnMapIt ( > + IN NIC_DATA *Nic, > + IN UINT64 MemAddr, > + IN UINT32 Size, > + IN UINT32 Direction, > + IN UINT64 MappedAddr > + ); > + > +VOID > +UndiGetState ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiStart ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiStop ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiGetInitInfo ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiGetConfigInfo ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiInitialize ( > + IN PXE_CDB *Cdb, > + IN OUT NIC_DATA *Nic > + ); > + > +VOID > +UndiReset ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiShutdown ( > + IN PXE_CDB *Cdb, > + IN OUT NIC_DATA *Nic > + ); > + > +VOID > +UndiInterruptEnable ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiReceiveFilter ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiStationAddress ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiStatistics ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiMcastIp2Mac ( > + IN OUT PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiNvData ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiGetStatus ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiFillHeader ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiTransmit ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +VOID > +UndiReceive ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +UINT16 > +Initialize ( > + IN PXE_CDB *Cdb, > + IN OUT NIC_DATA *Nic > + ); > + > +UINT16 > +Transmit ( > + IN PXE_CDB *Cdb, > + IN OUT NIC_DATA *Nic, > + IN UINT64 CpbAddr, > + IN UINT16 OpFlags > + ); > + > +UINT16 > +Receive ( > + IN PXE_CDB *Cdb, > + IN OUT NIC_DATA *Nic, > + IN UINT64 CpbAddr, > + IN OUT UINT64 DbAddr > + ); > + > +UINT16 > +SetFilter ( > + IN NIC_DATA *Nic, > + IN UINT16 SetFilter, > + IN UINT64 CpbAddr, > + IN UINT32 CpbSize > + ); > + > +UINT16 > +Statistics ( > + IN NIC_DATA *Nic, > + IN UINT64 DbAddr, > + IN UINT16 DbSize > + ); > + > +#endif > diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.h b/UsbNetworkPkg/UsbRndis/U= sbRndis.h > new file mode 100644 > index 000000000000..775807042460 > --- /dev/null > +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.h > @@ -0,0 +1,586 @@ > +/** @file > + Header file for for USB Rndis driver > + > + Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#ifndef _USB_RNDIS_H_ > +#define _USB_RNDIS_H_ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +typedef struct _REMOTE_NDIS_MSG_HEADER REMOTE_NDIS_MSG_HEADER; > + > +typedef struct { > + UINT32 Signature; > + EDKII_USB_ETHERNET_PROTOCOL UsbEth; > + EFI_HANDLE UsbCdcDataHandle; > + EFI_HANDLE UsbRndisHandle; > + EFI_USB_IO_PROTOCOL *UsbIo; > + EFI_USB_IO_PROTOCOL *UsbIoCdcData; > + EFI_USB_CONFIG_DESCRIPTOR *Config; > + UINT8 NumOfInterface; > + UINT8 BulkInEndpoint; > + UINT8 BulkOutEndpoint; > + UINT8 InterrupEndpoint; > + EFI_MAC_ADDRESS MacAddress; > + UINT32 RequestId; > + UINT32 Medium; > + UINT32 MaxPacketsPerTransfer; > + UINT32 MaxTransferSize; > + UINT32 PacketAlignmentFactor; > + LIST_ENTRY ReceivePacketList; > +} USB_RNDIS_DEVICE; > + > +#define USB_RNDIS_DRIVER_VERSION 1 > +#define USB_TX_ETHERNET_BULK_TIMEOUT 3000 > +#define USB_RX_ETHERNET_BULK_TIMEOUT 3 > +#define USB_ETHERNET_TRANSFER_TIMEOUT 200 > + > +#define LAN_BULKIN_CMD_CONTROL 1 > +#define MAXIMUM_STOPBULKIN_CNT 300 // Indicating maximum cou= nts for waiting bulk in command > +#define MINIMUM_STOPBULKIN_CNT 3 // Indicating minimum cou= nts for waiting bulk in command > +#define BULKIN_CMD_POLLING_CNT 300 // Indicating the waiting= counts for send bulk in command when system pending > +#define RNDIS_RESERVED_BYTE_LENGTH 8 > + > +#define USB_RNDIS_SIGNATURE SIGNATURE_32('r', 'n', 'd', 's') > +#define USB_RNDIS_DEVICE_FROM_THIS(a) CR (a, USB_RNDIS_DEVICE, UsbEth, = USB_RNDIS_SIGNATURE) > + > +extern EFI_COMPONENT_NAME2_PROTOCOL gUsbRndisComponentName2; > + > +struct BIT_MAP { > + unsigned int Src; > + unsigned int Dst; > +}; > + > +EFI_STATUS > +EFIAPI > +UsbRndisDriverSupported ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > + ); > + > +EFI_STATUS > +EFIAPI > +UsbRndisDriverStart ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > + ); > + > +EFI_STATUS > +EFIAPI > +UsbRndisDriverStop ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN UINTN NumberOfChildren, > + IN EFI_HANDLE *ChildHandleBuffer > + ); > + > +EFI_STATUS > +LoadAllDescriptor ( > + IN EFI_USB_IO_PROTOCOL *UsbIo, > + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc > + ); > + > +BOOLEAN > +NextDescriptor ( > + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, > + IN OUT UINTN *Offset > + ); > + > +EFI_STATUS > +GetFunctionalDescriptor ( > + IN EFI_USB_CONFIG_DESCRIPTOR *Config, > + IN UINT8 FunDescriptorType, > + OUT VOID *DataBuffer > + ); > + > +VOID > +GetEndpoint ( > + IN EFI_USB_IO_PROTOCOL *UsbIo, > + IN OUT USB_RNDIS_DEVICE *UsbRndisDevice > + ); > + > +EFI_STATUS > +EFIAPI > +UsbRndisInterrupt ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN BOOLEAN IsNewTransfer, > + IN UINTN PollingInterval, > + IN EFI_USB_DEVICE_REQUEST *Requst > + ); > + > +EFI_STATUS > +EFIAPI > +InterruptCallback ( > + IN VOID *Data, > + IN UINTN DataLength, > + IN VOID *Context, > + IN UINT32 Status > + ); > + > +EFI_STATUS > +EFIAPI > +GetUsbEthMacAddress ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT EFI_MAC_ADDRESS *MacAddress > + ); > + > +EFI_STATUS > +EFIAPI > +UsbEthBulkSize ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT UINTN *BulkSize > + ); > + > +EFI_STATUS > +EFIAPI > +RndisDummyReturn ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +EFI_STATUS > +EFIAPI > +RndisUndiStart ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +EFI_STATUS > +EFIAPI > +RndisUndiStop ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +EFI_STATUS > +EFIAPI > +RndisUndiGetInitInfo ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +EFI_STATUS > +EFIAPI > +RndisUndiGetConfigInfo ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +EFI_STATUS > +EFIAPI > +RndisUndiInitialize ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +EFI_STATUS > +EFIAPI > +RndisUndiTransmit ( > + IN PXE_CDB *Cdb, > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN VOID *BulkOutData, > + IN OUT UINTN *DataLength > + ); > + > +EFI_STATUS > +EFIAPI > +RndisUndiReceive ( > + IN PXE_CDB *Cdb, > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN OUT VOID *BulkInData, > + IN OUT UINTN *DataLength > + ); > + > +EFI_STATUS > +EFIAPI > +RndisUndiReset ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +EFI_STATUS > +EFIAPI > +RndisUndiShutdown ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +EFI_STATUS > +EFIAPI > +RndisUndiReceiveFilter ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +EFI_STATUS > +EFIAPI > +RndisUndiGetStatus ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ); > + > +EFI_STATUS > +EFIAPI > +GetUsbHeaderFunDescriptor ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor > + ); > + > +EFI_STATUS > +EFIAPI > +GetUsbUnionFunDescriptor ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor > + ); > + > +EFI_STATUS > +EFIAPI > +GetUsbRndisFunDescriptor ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor > + ); > + > +EFI_STATUS > +EFIAPI > +SetUsbRndisMcastFilter ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 Value, > + IN VOID *McastAddr > + ); > + > +EFI_STATUS > +EFIAPI > +SetUsbRndisPowerFilter ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 Value, > + IN UINT16 Length, > + IN VOID *PatternFilter > + ); > + > +EFI_STATUS > +EFIAPI > +GetUsbRndisPowerFilter ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 Value, > + IN BOOLEAN *PatternActive > + ); > + > +EFI_STATUS > +EFIAPI > +SetUsbRndisPacketFilter ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 Value > + ); > + > +EFI_STATUS > +EFIAPI > +GetRndisStatistic ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 Value, > + IN VOID *Statistic > + ); > + > +EFI_STATUS > +RndisControlMsg ( > + IN USB_RNDIS_DEVICE *UsbRndisDevice, > + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, > + OUT REMOTE_NDIS_MSG_HEADER *RndisMsgResponse > + ); > + > +EFI_STATUS > +RndisTransmitDataMsg ( > + IN USB_RNDIS_DEVICE *UsbRndisDevice, > + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, > + UINTN *TransferLength > + ); > + > +EFI_STATUS > +RndisReceiveDataMsg ( > + IN USB_RNDIS_DEVICE *UsbRndisDevice, > + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, > + UINTN *TransferLength > + ); > + > +VOID > +PrintRndisMsg ( > + IN REMOTE_NDIS_MSG_HEADER *RndisMsg > + ); > + > +#define RNDIS_MAJOR_VERSION 0x00000001 > +#define RNDIS_MINOR_VERSION 0x00000000 > +#define RNDIS_MAX_TRANSFER_SIZE 0x4000 > + > +#define RNDIS_PACKET_MSG 0x00000001 > +#define RNDIS_INITIALIZE_MSG 0x00000002 > +#define RNDIS_INITIALIZE_CMPLT 0x80000002 > +#define RNDIS_HLT_MSG 0x00000003 > +#define RNDIS_QUERY_MSG 0x00000004 > +#define RNDIS_QUERY_CMPLT 0x80000004 > +#define RNDIS_SET_MSG 0x00000005 > +#define RNDIS_SET_CMPLT 0x80000005 > +#define RNDIS_RESET_MSG 0x00000006 > +#define RNDIS_RESET_CMPLT 0x80000006 > +#define RNDIS_INDICATE_STATUS_MSG 0x00000007 > +#define RNDIS_KEEPALIVE_MSG 0x00000008 > +#define RNDIS_KEEPALIVE_CMPLT 0x80000008 > + > +#define RNDIS_STATUS_SUCCESS 0x00000000 > +#define RNDIS_STATUS_FAILURE 0xC0000001 > +#define RNDIS_STATUS_INVALID_DATA 0xC0010015 > +#define RNDIS_STATUS_NOT_SUPPORTED 0xC00000BB > +#define RNDIS_STATUS_MEDIA_CONNECT 0x4001000B > +#define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000C > + > +#define RNDIS_CONTROL_TIMEOUT 10000 // 10sec > +#define RNDIS_KEEPALIVE_TIMEOUT 5000 // 5sec > + > +#define SEND_ENCAPSULATED_COMMAND 0x00000000 > +#define GET_ENCAPSULATED_RESPONSE 0x00000001 > + > +// > +// General Objects > +// > +// Taken from NTDDNDIS.H > +#define OID_GEN_SUPPORTED_LIST 0x00010101 > +#define OID_GEN_HARDWARE_STATUS 0x00010102 > +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 > +#define OID_GEN_MEDIA_IN_USE 0x00010104 > +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 > +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 > +#define OID_GEN_LINK_SPEED 0x00010107 > +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 > +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 > +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A > +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B > +#define OID_GEN_VENDOR_ID 0x0001010C > +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D > +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E > +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F > +#define OID_GEN_DRIVER_VERSION 0x00010110 > +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 > +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 > +#define OID_GEN_MAC_OPTIONS 0x00010113 > +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 > +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 > +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 > + > +#define OID_GEN_XMIT_OK 0x00020101 > +#define OID_GEN_RCV_OK 0x00020102 > +#define OID_GEN_XMIT_ERROR 0x00020103 > +#define OID_GEN_RCV_ERROR 0x00020104 > +#define OID_GEN_RCV_NO_BUFFER 0x00020105 > + > +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 > +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 > +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 > +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 > +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 > +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 > +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 > +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 > +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 > +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A > +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B > +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C > +#define OID_GEN_RCV_CRC_ERROR 0x0002020D > +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E > + > +#define OID_802_3_CURRENT_ADDRESS 0x01010102 > +// > +// Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER). > +// > +#define NDIS_PACKET_TYPE_DIRECTED 0x0001 > +#define NDIS_PACKET_TYPE_MULTICAST 0x0002 > +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004 > +#define NDIS_PACKET_TYPE_BROADCAST 0x0008 > +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010 > +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020 > +#define NDIS_PACKET_TYPE_SMT 0x0040 > +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x0080 > +#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000 > +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000 > +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000 > +#define NDIS_PACKET_TYPE_GROUP 0x1000 > + > +#pragma pack(1) > + > +typedef struct _REMOTE_NDIS_MSG_HEADER { > + UINT32 MessageType; > + UINT32 MessageLength; > +} REMOTE_NDIS_MSG_HEADER; > + > +typedef struct { > + UINT32 MessageType; > + UINT32 MessageLength; > + UINT32 RequestID; > + UINT32 MajorVersion; > + UINT32 MinorVersion; > + UINT32 MaxTransferSize; > +} REMOTE_NDIS_INITIALIZE_MSG; > + > +typedef struct { > + UINT32 MessageType; > + UINT32 MessageLength; > + UINT32 RequestID; > +} REMOTE_NDIS_HALT_MSG; > + > +typedef struct { > + UINT32 MessageType; > + UINT32 MessageLength; > + UINT32 RequestID; > + UINT32 Oid; > + UINT32 InformationBufferLength; > + UINT32 InformationBufferOffset; > + UINT32 Reserved; > +} REMOTE_NDIS_QUERY_MSG; > + > +typedef struct { > + REMOTE_NDIS_QUERY_MSG QueryMsg; > + UINT8 Addr[6]; > +} REMOTE_NDIS_QUERY_MAC_MSG; > + > +typedef struct { > + REMOTE_NDIS_QUERY_MSG QueryMsg; > + UINT32 MaxTotalSize; > +} REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG; > + > +typedef struct { > + UINT32 MessageType; > + UINT32 MessageLength; > + UINT32 RequestID; > + UINT32 Oid; > + UINT32 InformationBufferLength; > + UINT32 InformationBufferOffset; > + UINT32 Reserved; > +} REMOTE_NDIS_SET_MSG; > + > +typedef struct { > + UINT32 MessageType; > + UINT32 MessageLength; > + UINT32 Reserved; > +} REMOTE_NDIS_RESET_MSG; > + > +typedef struct { > + UINT32 MessageType; > + UINT32 MessageLength; > + UINT32 Status; > + UINT32 StatusBufferLength; > + UINT32 StatusBufferOffset; > +} REMOTE_NDIS_INDICATE_STATUS_MSG; > + > +typedef struct { > + UINT32 DiagStatus; > + UINT32 ErrorOffset; > +} RNDIS_DIAGNOSTIC_INFO; > + > +typedef struct { > + UINT32 MessageType; > + UINT32 MessageLength; > + UINT32 RequestID; > +} REMOTE_NDIS_KEEPALIVE_MSG; > + > +typedef struct { > + UINT32 MessageType; > + UINT32 MessageLength; > + UINT32 RequestID; > + UINT32 Status; > + UINT32 MajorVersion; > + UINT32 MinorVersion; > + UINT32 DeviceFlags; > + UINT32 Medium; > + UINT32 MaxPacketsPerTransfer; > + UINT32 MaxTransferSize; > + UINT32 PacketAlignmentFactor; > + UINT64 Reserved; > +} REMOTE_NDIS_INITIALIZE_CMPLT; > + > +typedef struct { > + UINT32 MessageType; > + UINT32 MessageLength; > + UINT32 RequestID; > + UINT32 Status; > + UINT32 InformationBufferLength; > + UINT32 InformationBufferOffset; > +} REMOTE_NDIS_QUERY_CMPLT; > + > +typedef struct { > + REMOTE_NDIS_QUERY_CMPLT QueryCmplt; > + UINT8 Addr[6]; > +} REMOTE_NDIS_QUERY_MAC_CMPLT; > + > +typedef struct { > + REMOTE_NDIS_QUERY_CMPLT QueryCmplt; > + UINT32 MaxTotalSize; > +} REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_CMPLT; > + > +typedef struct { > + UINT32 MessageType; > + UINT32 MessageLength; > + UINT32 RequestID; > + UINT32 Status; > +} REMOTE_NDIS_SET_CMPLT; > + > +typedef struct { > + UINT32 MessageType; > + UINT32 MessageLength; > + UINT32 Status; > + UINT32 AddressingReset; > +} REMOTE_NDIS_RESET_CMPLT; > + > +typedef struct { > + UINT32 MessageType; > + UINT32 MessageLength; > + UINT32 RequestID; > + UINT32 Status; > +} REMOTE_NDIS_KEEPALIVE_CMPLT; > + > +typedef struct { > + UINT32 MessageType; > + UINT32 MessageLength; > + UINT32 DataOffset; > + UINT32 DataLength; > + UINT32 OutOfBandDataOffset; > + UINT32 OutOfBandDataLength; > + UINT32 NumOutOfBandDataElements; > + UINT32 PerPacketInfoOffset; > + UINT32 PerPacketInfoLength; > + UINT32 Reserved1; > + UINT32 Reserved2; > +} REMOTE_NDIS_PACKET_MSG; > + > +typedef struct { > + UINT32 Size; > + UINT32 Type; > + UINT32 ClassInformationOffset; > +} OUT_OF_BAND_DATA_RECORD; > + > +typedef struct { > + UINT32 Size; > + UINT32 Type; > + UINT32 ClassInformationOffset; > +} PER_PACKET_INFO_DATA_RECORD; > + > +typedef struct { > + LIST_ENTRY PacketList; > + UINT8 *OrgBuffer; > + UINTN RemainingLength; > + UINT8 *PacketStartBuffer; // Variable size data to follow > +} PACKET_LIST; > + > +#pragma pack() > + > +#endif > diff --git a/UsbNetworkPkg/NetworkCommon/ComponentName.c b/UsbNetworkPkg/= NetworkCommon/ComponentName.c > new file mode 100644 > index 000000000000..e83469e13079 > --- /dev/null > +++ b/UsbNetworkPkg/NetworkCommon/ComponentName.c > @@ -0,0 +1,263 @@ > +/** @file > + This file contains code for USB network common driver > + component name definitions > + > + Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#include "DriverBinding.h" > + > +extern EFI_DRIVER_BINDING_PROTOCOL gNetworkCommonDriverBinding; > + > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE gNetworkCommonDr= iverNameTable[] =3D { > + { > + "eng;en", > + L"Network Common Driver" > + }, > + { > + NULL, > + NULL > + } > +}; > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gNetworkCommonC= ontrollerNameTable =3D NULL; > + > +EFI_STATUS > +EFIAPI > +NetworkCommonComponentNameGetDriverName ( > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > + IN CHAR8 *Language, > + OUT CHAR16 **DriverName > + ); > + > +EFI_STATUS > +EFIAPI > +NetworkCommonComponentNameGetControllerName ( > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > + IN EFI_HANDLE Controller, > + IN EFI_HANDLE ChildHandle OPTIONAL, > + IN CHAR8 *Language, > + OUT CHAR16 **ControllerName > + ); > + > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gNetworkCommo= nComponentName =3D { > + NetworkCommonComponentNameGetDriverName, > + NetworkCommonComponentNameGetControllerName, > + "eng" > +}; > + > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gNetworkComm= onComponentName2 =3D { > + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)NetworkCommonComponentNameGetDriv= erName, > + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)NetworkCommonComponentNameGet= ControllerName, > + "en" > +}; > + > +/** > + Retrieves a Unicode string that is the user readable name of the drive= r. > + > + This function retrieves the user readable name of a driver in the form= of a > + Unicode string. If the driver specified by This has a user readable na= me in > + the language specified by Language, then a pointer to the driver name = is > + returned in DriverName, and EFI_SUCCESS is returned. If the driver spe= cified > + by This does not support the language specified by Language, > + then EFI_UNSUPPORTED is returned. > + > + @param[in] This A pointer to the EFI_COMPONENT_NAME2_PRO= TOCOL or > + EFI_COMPONENT_NAME_PROTOCOL instance. > + @param[in] Language A pointer to a Null-terminated ASCII str= ing > + array indicating the language. This is t= he > + language of the driver name that the cal= ler is > + requesting, and it must match one of the > + languages specified in SupportedLanguage= s. The > + number of languages supported by a drive= r is up > + to the driver writer. Language is specif= ied > + in RFC 4646 or ISO 639-2 language code f= ormat. > + @param[out] DriverName A pointer to the Unicode string to retur= n. > + This Unicode string is the name of the > + driver specified by This in the language > + specified by Language. > + > + @retval EFI_SUCCESS The Unicode string for the Driver specif= ied by > + This and the language specified by Langu= age was > + returned in DriverName. > + @retval EFI_INVALID_PARAMETER Language is NULL. > + @retval EFI_INVALID_PARAMETER DriverName is NULL. > + @retval EFI_UNSUPPORTED The driver specified by This does not su= pport > + the language specified by Language. > + > +**/ > +EFI_STATUS > +EFIAPI > +NetworkCommonComponentNameGetDriverName ( > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > + IN CHAR8 *Language, > + OUT CHAR16 **DriverName > + ) > +{ > + return LookupUnicodeString2 ( > + Language, > + This->SupportedLanguages, > + gNetworkCommonDriverNameTable, > + DriverName, > + (BOOLEAN)(This =3D=3D &gNetworkCommonComponentName) > + ); > +} > + > +/** > + Retrieves a Unicode string that is the user readable name of the contr= oller > + that is being managed by a driver. > + > + This function retrieves the user readable name of the controller speci= fied by > + ControllerHandle and ChildHandle in the form of a Unicode string. If t= he > + driver specified by This has a user readable name in the language spec= ified by > + Language, then a pointer to the controller name is returned in Control= lerName, > + and EFI_SUCCESS is returned. If the driver specified by This is not c= urrently > + managing the controller specified by ControllerHandle and ChildHandle, > + then EFI_UNSUPPORTED is returned. If the driver specified by This doe= s not > + support the language specified by Language, then EFI_UNSUPPORTED is re= turned. > + > + @param[in] This A pointer to the EFI_COMPONENT_NAME2_PRO= TOCOL or > + EFI_COMPONENT_NAME_PROTOCOL instance. > + @param[in] Controller The handle of a controller that the driv= er > + specified by This is managing. This han= dle > + specifies the controller whose name is t= o be > + returned. > + @param[in] ChildHandle The handle of the child controller to re= trieve > + the name of. This is an optional parame= ter 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 bu= s > + controller. It will not be NULL for a b= us > + driver that wishes to retrieve the name = of a > + child controller. > + @param[in] Language A pointer to a Null-terminated ASCII str= ing > + array indicating the language. This is = the > + language of the driver name that the cal= ler is > + requesting, and it must match one of the > + languages specified in SupportedLanguage= s. The > + number of languages supported by a drive= r is up > + to the driver writer. Language is specif= ied in > + RFC 4646 or ISO 639-2 language code form= at. > + @param[out] ControllerName A pointer to the Unicode string to retur= n. > + 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 d= river > + specified by This. > + > + @retval EFI_SUCCESS The Unicode string for the user readable= name in > + the language specified by Language for t= he > + driver specified by This was returned in > + DriverName. > + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HAND= LE. > + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a = valid > + EFI_HANDLE. > + @retval EFI_INVALID_PARAMETER Language is NULL. > + @retval EFI_INVALID_PARAMETER ControllerName is NULL. > + @retval EFI_UNSUPPORTED The driver specified by This is not curr= ently > + managing the controller specified by > + ControllerHandle and ChildHandle. > + @retval EFI_UNSUPPORTED The driver specified by This does not su= pport > + the language specified by Language. > + > +**/ > +EFI_STATUS > +EFIAPI > +NetworkCommonComponentNameGetControllerName ( > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > + IN EFI_HANDLE Controller, > + IN EFI_HANDLE ChildHandle OPTIONAL, > + IN CHAR8 *Language, > + OUT CHAR16 **ControllerName > + ) > +{ > + EFI_STATUS Status; > + CHAR16 *HandleName; > + EFI_USB_IO_PROTOCOL *UsbIo; > + EFI_USB_DEVICE_DESCRIPTOR DevDesc; > + > + if (!Language || !ControllerName) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (ChildHandle =3D=3D NULL) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // Make sure this driver is currently managing ControllerHandle > + // > + Status =3D EfiTestManagedDevice ( > + Controller, > + gNetworkCommonDriverBinding.DriverBindingHandle, > + &gEdkIIUsbEthProtocolGuid > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Make sure this driver produced ChildHandle > + // > + Status =3D EfiTestChildHandle ( > + Controller, > + ChildHandle, > + &gEdkIIUsbEthProtocolGuid > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D gBS->HandleProtocol (Controller, &gEfiUsbIoProtocolGuid, (V= OID **)&UsbIo); > + > + if (!EFI_ERROR (Status)) { > + Status =3D UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D UsbIo->UsbGetStringDescriptor (UsbIo, 0x409, DevDesc.StrM= anufacturer, &HandleName); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *ControllerName =3D HandleName; > + > + if (gNetworkCommonControllerNameTable !=3D NULL) { > + FreeUnicodeStringTable (gNetworkCommonControllerNameTable); > + gNetworkCommonControllerNameTable =3D NULL; > + } > + > + Status =3D AddUnicodeString2 ( > + "eng", > + gNetworkCommonComponentName.SupportedLanguages, > + &gNetworkCommonControllerNameTable, > + HandleName, > + TRUE > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D AddUnicodeString2 ( > + "en", > + gNetworkCommonComponentName2.SupportedLanguages, > + &gNetworkCommonControllerNameTable, > + HandleName, > + FALSE > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + return LookupUnicodeString2 ( > + Language, > + This->SupportedLanguages, > + gNetworkCommonControllerNameTable, > + ControllerName, > + (BOOLEAN)(This =3D=3D &gNetworkCommonComponentName) > + ); > + } > + > + return EFI_UNSUPPORTED; > +} > diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.c b/UsbNetworkPkg/= NetworkCommon/DriverBinding.c > new file mode 100644 > index 000000000000..23b791362091 > --- /dev/null > +++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.c > @@ -0,0 +1,595 @@ > +/** @file > + This file contains code for USB network binding driver > + > + Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#include "DriverBinding.h" > + > +PXE_SW_UNDI *gPxe =3D NULL; > +NIC_DEVICE *gLanDeviceList[MAX_LAN_INTERFACE]; > +UINT32 gRateLimitingCredit; > +UINT32 gRateLimitingPollTimer; > +BOOLEAN gRateLimitingEnable; > + > +EFI_DRIVER_BINDING_PROTOCOL gNetworkCommonDriverBinding =3D { > + NetworkCommonSupported, > + NetworkCommonDriverStart, > + NetworkCommonDriverStop, > + NETWORK_COMMON_DRIVER_VERSION, > + NULL, > + NULL > +}; > + > +/** > + Create MAC Device Path > + > + @param[in, out] Dev A pointer to the EFI_DEVICE_PATH_PROTO= COL instance. > + @param[in] BaseDev A pointer to the EFI_DEVICE_PATH_PROTO= COL instance. > + @param[in] Nic A pointer to the Network interface con= troller data. > + > + @retval EFI_OUT_OF_RESOURCES The device path could not be created s= uccessfully due to a lack of resources. > + @retval EFI_SUCCESS MAC device path created successfully. > + > +**/ > +EFI_STATUS > +CreateMacDevicePath ( > + IN OUT EFI_DEVICE_PATH_PROTOCOL **Dev, > + IN EFI_DEVICE_PATH_PROTOCOL *BaseDev, > + IN NIC_DATA *Nic > + ) > +{ > + EFI_STATUS Status; > + MAC_ADDR_DEVICE_PATH MacAddrNode; > + EFI_DEVICE_PATH_PROTOCOL *EndNode; > + UINT8 *DevicePath; > + UINT16 TotalLength; > + UINT16 BaseLength; > + > + ZeroMem (&MacAddrNode, sizeof (MAC_ADDR_DEVICE_PATH)); > + CopyMem (&MacAddrNode.MacAddress, &Nic->MacAddr, sizeof (EFI_MAC_ADDRE= SS)); > + > + MacAddrNode.Header.Type =3D MESSAGING_DEVICE_PATH; > + MacAddrNode.Header.SubType =3D MSG_MAC_ADDR_DP; > + MacAddrNode.Header.Length[0] =3D (UINT8)sizeof (MacAddrNode); > + MacAddrNode.Header.Length[1] =3D 0; > + > + EndNode =3D BaseDev; > + > + while (!IsDevicePathEnd (EndNode)) { > + EndNode =3D NextDevicePathNode (EndNode); > + } > + > + BaseLength =3D (UINT16)((UINTN)(EndNode) - (UINTN)(BaseDev)); > + TotalLength =3D (UINT16)(BaseLength + sizeof (MacAddrNode) + sizeof (E= FI_DEVICE_PATH_PROTOCOL)); > + > + Status =3D gBS->AllocatePool (EfiBootServicesData, TotalLength, (VOID = **)&DevicePath); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *Dev =3D (EFI_DEVICE_PATH_PROTOCOL *)DevicePath; > + CopyMem (DevicePath, (CHAR8 *)BaseDev, BaseLength); > + DevicePath +=3D BaseLength; > + CopyMem (DevicePath, (CHAR8 *)&MacAddrNode, sizeof (MacAddrNode)); > + DevicePath +=3D sizeof (MacAddrNode); > + CopyMem (DevicePath, (CHAR8 *)EndNode, sizeof (EFI_DEVICE_PATH_PROTOCO= L)); > + > + return EFI_SUCCESS; > +} > + > +/** > + Network Common Driver Binding Support. > + > + @param[in] This Protocol instance pointer. > + @param[in] ControllerHandle Handle of device to test. > + @param[in] RemainingDevicePath Optional parameter use to pick a s= pecific child > + device to start. > + > + @retval EFI_SUCCESS This driver supports this device. > + @retval EFI_ALREADY_STARTED This driver is already running on = this device. > + @retval other This driver does not support this = device. > + > +**/ > +EFI_STATUS > +EFIAPI > +NetworkCommonSupported ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > + ) > +{ > + EFI_STATUS Status; > + EDKII_USB_ETHERNET_PROTOCOL *UsbEth; > + > + Status =3D gBS->OpenProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + (VOID **)&UsbEth, > + This->DriverBindingHandle, > + ControllerHandle, > + EFI_OPEN_PROTOCOL_BY_DRIVER > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + return Status; > +} > + > +/** > + Network Common Driver Binding Start. > + > + @param[in] This Protocol instance pointer. > + @param[in] ControllerHandle Handle of device to bind driver to= . > + @param[in] RemainingDevicePath Optional parameter use to pick a s= pecific child > + device to start. > + > + @retval EFI_SUCCESS This driver is added to Controller= Handle > + @retval EFI_DEVICE_ERROR This driver could not be started d= ue to a device error > + @retval EFI_OUT_OF_RESOURCES The driver could not install succe= ssfully due to a lack of resources. > + @retval other This driver does not support this = device > + > +**/ > +EFI_STATUS > +EFIAPI > +NetworkCommonDriverStart ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > + ) > +{ > + EFI_STATUS Status; > + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath; > + EDKII_USB_ETHERNET_PROTOCOL *UsbEth; > + EFI_MAC_ADDRESS MacAddress; > + UINTN BulkDataSize; > + NIC_DEVICE *NicDevice; > + UINT8 *TmpPxePointer; > + > + Status =3D gBS->OpenProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + (VOID **)&UsbEth, > + This->DriverBindingHandle, > + ControllerHandle, > + EFI_OPEN_PROTOCOL_BY_DRIVER > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D gBS->OpenProtocol ( > + ControllerHandle, > + &gEfiDevicePathProtocolGuid, > + (VOID **)&UsbEthPath, > + This->DriverBindingHandle, > + ControllerHandle, > + EFI_OPEN_PROTOCOL_BY_DRIVER > + ); > + > + if (EFI_ERROR (Status)) { > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + return Status; > + } > + > + ZeroMem (&MacAddress, sizeof (EFI_MAC_ADDRESS)); > + > + Status =3D UsbEth->UsbEthMacAddress (UsbEth, &MacAddress); > + ASSERT_EFI_ERROR (Status); > + Status =3D UsbEth->UsbEthMaxBulkSize (UsbEth, &BulkDataSize); > + > + if (EFI_ERROR (Status)) { > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiDevicePathProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + return Status; > + } > + > + NicDevice =3D AllocateZeroPool (sizeof (NIC_DEVICE) + BulkDataSize + 4= 096); > + if (!NicDevice) { > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiDevicePathProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + return EFI_OUT_OF_RESOURCES; > + } > + > + // for alignment adjustment > + if (gPxe =3D=3D NULL) { > + TmpPxePointer =3D NULL; > + TmpPxePointer =3D AllocateZeroPool (sizeof (PXE_SW_UNDI) + 16); > + if (!TmpPxePointer) { > + if (NicDevice !=3D NULL) { > + FreePool (NicDevice); > + } > + > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiDevicePathProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + > + return EFI_OUT_OF_RESOURCES; > + } else { > + // check for paragraph alignment here > + if (((UINTN)TmpPxePointer & 0x0F) !=3D 0) { > + gPxe =3D (PXE_SW_UNDI *)(TmpPxePointer + 8); > + } else { > + gPxe =3D (PXE_SW_UNDI *)TmpPxePointer; > + } > + > + if (!gPxe) { > + if (NicDevice !=3D NULL) { > + FreePool (NicDevice); > + } > + > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiDevicePathProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + return EFI_OUT_OF_RESOURCES; > + } > + > + PxeStructInit (gPxe); > + } > + } > + > + NicDevice->NiiProtocol.Id =3D (UINT64)(UINTN)(gPxe); > + NicDevice->NiiProtocol.IfNum =3D gPxe->IFcnt | gPxe->IFcntExt << 8; > + > + UpdateNicNum (&NicDevice->NicInfo, gPxe); > + > + NicDevice->NicInfo.Signature =3D NIC_DATA_SIGNATURE; > + > + NicDevice->NicInfo.UsbEth =3D UsbEth; > + NicDevice->NicInfo.MaxSegmentSize =3D (UINT16)BulkDataSize; > + NicDevice->NicInfo.CableDetect =3D 0; > + NicDevice->ReceiveBuffer =3D ALIGN_POINTER ((VOID *)NicDevice= , 4096); > + > + CopyMem ((CHAR8 *)&(NicDevice->NicInfo.MacAddr), (CHAR8 *)&MacAddress,= sizeof (MacAddress)); > + > + NicDevice->NicInfo.TxBufferCount =3D 0; > + > + if (NicDevice->NiiProtocol.IfNum < MAX_LAN_INTERFACE) { > + gLanDeviceList[NicDevice->NiiProtocol.IfNum] =3D NicDevice; > + } else { > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiDevicePathProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + > + if (TmpPxePointer !=3D NULL) { > + FreePool (TmpPxePointer); > + } > + > + if (NicDevice !=3D NULL) { > + FreePool (NicDevice); > + } > + > + return EFI_DEVICE_ERROR; > + } > + > + Status =3D CreateMacDevicePath ( > + &NicDevice->DevPath, > + UsbEthPath, > + &NicDevice->NicInfo > + ); > + > + if (EFI_ERROR (Status)) { > + UpdateNicNum (NULL, gPxe); > + if (TmpPxePointer !=3D NULL) { > + FreePool (TmpPxePointer); > + } > + } > + > + NicDevice->Signature =3D UNDI_DEV_SIGNATURE; > + NicDevice->NiiProtocol.Revision =3D EFI_NETWORK_INTERFACE_IDENTIF= IER_PROTOCOL_REVISION; > + NicDevice->NiiProtocol.Type =3D EfiNetworkInterfaceUndi; > + NicDevice->NiiProtocol.MajorVer =3D PXE_ROMID_MAJORVER; > + NicDevice->NiiProtocol.MinorVer =3D PXE_ROMID_MINORVER; > + NicDevice->NiiProtocol.ImageSize =3D 0; > + NicDevice->NiiProtocol.ImageAddr =3D 0; > + NicDevice->NiiProtocol.Ipv6Supported =3D TRUE; > + > + NicDevice->NiiProtocol.StringId[0] =3D 'U'; > + NicDevice->NiiProtocol.StringId[1] =3D 'N'; > + NicDevice->NiiProtocol.StringId[2] =3D 'D'; > + NicDevice->NiiProtocol.StringId[3] =3D 'I'; > + NicDevice->DeviceHandle =3D NULL; > + > + NicDevice->NicInfo.RateLimitingEnable =3D gRateLimitingEnable; > + NicDevice->NicInfo.RateLimitingCreditCount =3D 0; > + NicDevice->NicInfo.RateLimitingCredit =3D gRateLimitingCredit; > + NicDevice->NicInfo.RateLimitingPollTimer =3D gRateLimitingPollTimer; > + NicDevice->NicInfo.RateLimiter =3D NULL; > + > + ZeroMem (&NicDevice->NicInfo.Request, sizeof (EFI_USB_DEVICE_REQUEST))= ; > + > + Status =3D UsbEth->UsbEthInterrupt (UsbEth, TRUE, NETWORK_COMMON_POLLI= NG_INTERVAL, &NicDevice->NicInfo.Request); > + ASSERT_EFI_ERROR (Status); > + > + Status =3D gBS->InstallMultipleProtocolInterfaces ( > + &NicDevice->DeviceHandle, > + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, > + &NicDevice->NiiProtocol, > + &gEfiDevicePathProtocolGuid, > + NicDevice->DevPath, > + NULL > + ); > + > + if (EFI_ERROR (Status)) { > + if (NicDevice->NiiProtocol.IfNum < MAX_LAN_INTERFACE) { > + gLanDeviceList[NicDevice->NiiProtocol.IfNum] =3D NULL; > + } > + > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiDevicePathProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + > + if (TmpPxePointer !=3D NULL) { > + FreePool (TmpPxePointer); > + } > + > + if (NicDevice->DevPath !=3D NULL) { > + FreePool (NicDevice->DevPath); > + } > + > + if (NicDevice !=3D NULL) { > + FreePool (NicDevice); > + } > + > + return EFI_DEVICE_ERROR; > + } > + > + Status =3D gBS->OpenProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + (VOID **)&UsbEth, > + This->DriverBindingHandle, > + NicDevice->DeviceHandle, > + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER > + ); > + > + return Status; > +} > + > +/** > + Network Common Driver Binding Stop. > + > + @param[in] This Protocol instance pointer. > + @param[in] ControllerHandle Handle of device to stop driver on > + @param[in] NumberOfChildren Number of Handles in ChildHandleBuff= er. If number of > + children is zero stop the entire bus= driver. > + @param[in] ChildHandleBuffer List of Child Handles to Stop. > + > + @retval EFI_SUCCESS This driver is removed ControllerHan= dle > + @retval other This driver was not removed from thi= s device > + > +**/ > +EFI_STATUS > +EFIAPI > +NetworkCommonDriverStop ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN UINTN NumberOfChildren, > + IN EFI_HANDLE *ChildHandleBuffer > + ) > +{ > + EFI_STATUS Status; > + BOOLEAN AllChildrenStopped; > + UINTN Index; > + EDKII_USB_ETHERNET_PROTOCOL *UsbEth; > + NIC_DEVICE *NicDevice; > + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol; > + > + if (NumberOfChildren =3D=3D 0) { > + Status =3D gBS->OpenProtocol ( > + ControllerHandle, > + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, > + (VOID **)&NiiProtocol, > + This->DriverBindingHandle, > + ControllerHandle, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + > + if (EFI_ERROR (Status)) { > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiDevicePathProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + return EFI_SUCCESS; > + } > + > + NicDevice =3D UNDI_DEV_FROM_THIS (NiiProtocol); > + Status =3D gBS->UninstallMultipleProtocolInterfaces ( > + ControllerHandle, > + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, > + &NicDevice->NiiProtocol, > + &gEfiDevicePathProtocolGuid, > + NicDevice->DevPath, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + FreePool (NicDevice->DevPath); > + FreePool (NicDevice); > + > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiDevicePathProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + return EFI_SUCCESS; > + } > + > + AllChildrenStopped =3D TRUE; > + > + for (Index =3D 0; Index < NumberOfChildren; Index++) { > + Status =3D gBS->OpenProtocol ( > + ChildHandleBuffer[Index], > + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, > + (VOID **)&NiiProtocol, > + This->DriverBindingHandle, > + ControllerHandle, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + if (EFI_ERROR (Status)) { > + AllChildrenStopped =3D FALSE; > + continue; > + } > + > + NicDevice =3D UNDI_DEV_FROM_THIS (NiiProtocol); > + > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + This->DriverBindingHandle, > + ChildHandleBuffer[Index] > + ); > + > + Status =3D gBS->UninstallMultipleProtocolInterfaces ( > + ChildHandleBuffer[Index], > + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, > + &NicDevice->NiiProtocol, > + &gEfiDevicePathProtocolGuid, > + NicDevice->DevPath, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + Status =3D gBS->OpenProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + (VOID **)&UsbEth, > + This->DriverBindingHandle, > + ChildHandleBuffer[Index], > + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER > + ); > + } else { > + FreePool (NicDevice->DevPath); > + FreePool (NicDevice); > + } > + } > + > + if (!AllChildrenStopped) { > + return EFI_DEVICE_ERROR; > + } > + > + return Status; > +} > + > +/** > + Entrypoint of Network Common Driver. > + > + This function is the entrypoint of Network Common Driver. It installs = Driver Binding > + Protocols together with Component Name Protocols. > + > + @param[in] ImageHandle The firmware allocated handle for the EF= I image. > + @param[in] SystemTable A pointer to the EFI System Table. > + > + @retval EFI_SUCCESS The entry point is executed successfully= . > + > +**/ > +EFI_STATUS > +EFIAPI > +NetworkCommonEntry ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + > + gNetworkCommonDriverBinding.DriverBindingHandle =3D ImageHandle; > + gNetworkCommonDriverBinding.ImageHandle =3D ImageHandle; > + gRateLimitingEnable =3D PcdGetBool (Enable= RateLimiting); > + gRateLimitingCredit =3D PcdGet32 (RateLimi= tingCredit); > + gRateLimitingPollTimer =3D PcdGet32 (RateLimi= tingFactor); > + > + Status =3D gBS->InstallMultipleProtocolInterfaces ( > + &gNetworkCommonDriverBinding.DriverBindingHandle, > + &gEfiDriverBindingProtocolGuid, > + &gNetworkCommonDriverBinding, > + &gEfiComponentName2ProtocolGuid, > + &gNetworkCommonComponentName2, > + NULL > + ); > + return Status; > +} > diff --git a/UsbNetworkPkg/NetworkCommon/PxeFunction.c b/UsbNetworkPkg/Ne= tworkCommon/PxeFunction.c > new file mode 100644 > index 000000000000..687cabca4ce3 > --- /dev/null > +++ b/UsbNetworkPkg/NetworkCommon/PxeFunction.c > @@ -0,0 +1,1803 @@ > +/** @file > + This file contains code for UNDI command based on UEFI specification. > + > + Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#include "DriverBinding.h" > + > +// API table, defined in UEFI specification > +API_FUNC gUndiApiTable[] =3D { > + UndiGetState, > + UndiStart, > + UndiStop, > + UndiGetInitInfo, > + UndiGetConfigInfo, > + UndiInitialize, > + UndiReset, > + UndiShutdown, > + UndiInterruptEnable, > + UndiReceiveFilter, > + UndiStationAddress, > + UndiStatistics, > + UndiMcastIp2Mac, > + UndiNvData, > + UndiGetStatus, > + UndiFillHeader, > + UndiTransmit, > + UndiReceive > +}; > + > +/** > + Callback function for enable Rate Limiter > + > + @param[in] Event Event whose notification function is being= invoked > + @param[in] Context Pointer to the notification function's con= text > + > +**/ > +VOID > +EFIAPI > +UndiRateLimiterCallback ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + NIC_DATA *Nic =3D Context; > + > + if (Nic->RateLimitingCreditCount < Nic->RateLimitingCredit) { > + Nic->RateLimitingCreditCount++; > + } > +} > + > +/** > + This command is used to determine the operational state of the UNDI. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiGetState ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_GET_STATE) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || > + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || > + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || > + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) || > + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + > + Cdb->StatFlags =3D Cdb->StatFlags | Nic->State; > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > +} > + > +/** > + This command is used to change the UNDI operational state from stopped= to started. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiStart ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + PXE_CPB_START_31 *Cpb; > + EFI_STATUS Status; > + BOOLEAN EventError; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_START) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->CPBsize !=3D sizeof (PXE_CPB_START_31)) || > + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || > + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) || > + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } > + > + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_STOPPED) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_ALREADY_STARTED; > + return; > + } > + > + Cpb =3D (PXE_CPB_START_31 *)(UINTN)Cdb->CPBaddr; > + > + Nic->PxeStart.Delay =3D Cpb->Delay; > + Nic->PxeStart.Virt2Phys =3D Cpb->Virt2Phys; > + Nic->PxeStart.Block =3D Cpb->Block; > + Nic->PxeStart.Map_Mem =3D 0; > + Nic->PxeStart.UnMap_Mem =3D 0; > + Nic->PxeStart.Sync_Mem =3D Cpb->Sync_Mem; > + Nic->PxeStart.Unique_ID =3D Cpb->Unique_ID; > + EventError =3D FALSE; > + Status =3D EFI_SUCCESS; > + if (Nic->RateLimitingEnable =3D=3D TRUE) { > + Status =3D gBS->CreateEvent ( > + EVT_TIMER | EVT_NOTIFY_SIGNAL, > + TPL_NOTIFY, > + UndiRateLimiterCallback, > + Nic, > + &Nic->RateLimiter > + ); > + if (!EFI_ERROR (Status)) { > + Status =3D gBS->SetTimer ( > + Nic->RateLimiter, > + TimerPeriodic, > + Nic->RateLimitingPollTimer * 10000 > + ); > + if (EFI_ERROR (Status)) { > + EventError =3D TRUE; > + } > + } > + } > + > + if ((Nic->UsbEth->UsbEthUndi.UsbEthUndiStart !=3D NULL) && (EventError= =3D=3D FALSE)) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStart (Cdb, Nic); > + } > + > + if (!EFI_ERROR (Status)) { > + // Initial the state for UNDI start. > + Nic->State =3D PXE_STATFLAGS_GET_STATE_STARTED; > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } else { > + if (Nic->RateLimitingEnable =3D=3D TRUE) { > + if (!EventError) { > + gBS->SetTimer (&Nic->RateLimiter, TimerCancel, 0); > + } > + > + if (Nic->RateLimiter) { > + gBS->CloseEvent (&Nic->RateLimiter); > + Nic->RateLimiter =3D 0; > + } > + } > + > + // Initial the state when UNDI start is fail > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_DEVICE_FAILURE; > + } > +} > + > +/** > + This command is used to change the UNDI operational state from started= to stopped. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiStop ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_STOP) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || > + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || > + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || > + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) || > + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + > + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_NOT_STARTED; > + return; > + } > + > + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_NOT_SHUTDOWN; > + return; > + } > + > + Nic->PxeStart.Delay =3D 0; > + Nic->PxeStart.Virt2Phys =3D 0; > + Nic->PxeStart.Block =3D 0; > + Nic->PxeStart.Map_Mem =3D 0; > + Nic->PxeStart.UnMap_Mem =3D 0; > + Nic->PxeStart.Sync_Mem =3D 0; > + Nic->State =3D PXE_STATFLAGS_GET_STATE_STOPPED; > + > + if (Nic->RateLimitingEnable =3D=3D TRUE) { > + gBS->SetTimer (&Nic->RateLimiter, TimerCancel, 0); > + gBS->CloseEvent (&Nic->RateLimiter); > + } > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStop !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStop (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > +} > + > +/** > + This command is used to retrieve initialization information that is > + needed by drivers and applications to initialized UNDI. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiGetInitInfo ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + PXE_DB_GET_INIT_INFO *Db; > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_GET_INIT_INFO) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || > + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || > + (Cdb->DBsize !=3D sizeof (PXE_DB_GET_INIT_INFO)) || > + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + > + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_NOT_STARTED; > + return; > + } > + > + Db =3D (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr; > + > + Db->MemoryRequired =3D MEMORY_REQUIRE; > + Db->FrameDataLen =3D PXE_MAX_TXRX_UNIT_ETHER; > + Db->LinkSpeeds[0] =3D 10; > + Db->LinkSpeeds[1] =3D 100; > + Db->LinkSpeeds[2] =3D 1000; > + Db->LinkSpeeds[3] =3D 0; > + Db->MediaHeaderLen =3D PXE_MAC_HEADER_LEN_ETHER; > + Db->HWaddrLen =3D PXE_HWADDR_LEN_ETHER; > + Db->MCastFilterCnt =3D MAX_MCAST_ADDRESS_CNT; > + Db->TxBufCnt =3D Nic->PxeInit.TxBufCnt; > + Db->TxBufSize =3D Nic->PxeInit.TxBufSize; > + Db->RxBufCnt =3D Nic->PxeInit.RxBufCnt; > + Db->RxBufSize =3D Nic->PxeInit.RxBufSize; > + Db->IFtype =3D PXE_IFTYPE_ETHERNET; > + Db->SupportedDuplexModes =3D PXE_DUPLEX_DEFAULT; > + Db->SupportedLoopBackModes =3D LOOPBACK_NORMAL; > + > + Cdb->StatFlags |=3D (PXE_STATFLAGS_CABLE_DETECT_SUPPORTED | > + PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED); > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > +} > + > +/** > + This command is used to retrieve configuration information about > + the NIC being controlled by the UNDI. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiGetConfigInfo ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + PXE_DB_GET_CONFIG_INFO *Db; > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_GET_CONFIG_INFO) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || > + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || > + (Cdb->DBsize !=3D sizeof (PXE_DB_GET_CONFIG_INFO)) || > + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + > + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_NOT_STARTED; > + return; > + } > + > + Db =3D (PXE_DB_GET_CONFIG_INFO *)(UINTN)Cdb->DBaddr; > + > + Db->pci.BusType =3D PXE_BUSTYPE_USB; > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo (Cdb, Nic= ); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > +} > + > +/** > + This command resets the network adapter and initializes UNDI using > + the parameters supplied in the CPB. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in, out] Nic A pointer to the Network interface controller dat= a. > + > +**/ > +VOID > +UndiInitialize ( > + IN PXE_CDB *Cdb, > + IN OUT NIC_DATA *Nic > + ) > +{ > + PXE_CPB_INITIALIZE *Cpb; > + PXE_DB_INITIALIZE *Db; > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_INITIALIZE) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->CPBsize !=3D sizeof (PXE_CPB_INITIALIZE))) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + } > + > + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_NOT_STARTED; > + return; > + } > + > + if ((Cdb->OpFlags !=3D PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) && > + (Cdb->OpFlags !=3D PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } > + > + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_ALREADY_INITIALIZED; > + return; > + } > + > + Cpb =3D (PXE_CPB_INITIALIZE *)(UINTN)Cdb->CPBaddr; > + Db =3D (PXE_DB_INITIALIZE *)(UINTN)Cdb->DBaddr; > + > + Nic->PxeInit.LinkSpeed =3D Cpb->LinkSpeed; > + Nic->PxeInit.DuplexMode =3D Cpb->DuplexMode; > + Nic->PxeInit.LoopBackMode =3D Cpb->LoopBackMode; > + Nic->PxeInit.MemoryAddr =3D Cpb->MemoryAddr; > + Nic->PxeInit.MemoryLength =3D Cpb->MemoryLength; > + Nic->PxeInit.TxBufCnt =3D TX_BUFFER_COUNT; > + Nic->PxeInit.TxBufSize =3D Nic->MaxSegmentSize; > + Nic->PxeInit.RxBufCnt =3D RX_BUFFER_COUNT; > + Nic->PxeInit.RxBufSize =3D Nic->MaxSegmentSize; > + > + Cdb->StatCode =3D Initialize (Cdb, Nic); > + > + Db->MemoryUsed =3D MEMORY_REQUIRE; > + Db->TxBufCnt =3D Nic->PxeInit.TxBufCnt; > + Db->TxBufSize =3D Nic->PxeInit.TxBufSize; > + Db->RxBufCnt =3D Nic->PxeInit.RxBufCnt; > + Db->RxBufSize =3D Nic->PxeInit.RxBufSize; > + > + Nic->RxFilter =3D PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; > + Nic->CanTransmit =3D FALSE; > + > + if (Cdb->OpFlags =3D=3D PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) { > + if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTION) && (Nic= ->Request.Value =3D=3D NETWORK_DISCONNECT)) { > + Nic->CableDetect =3D 0; > + } else if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTION) = && (Nic->Request.Value =3D=3D NETWORK_CONNECTED)) { > + Nic->CableDetect =3D 1; > + } > + > + if (Nic->CableDetect =3D=3D 0) { > + Cdb->StatFlags |=3D PXE_STATFLAGS_INITIALIZED_NO_MEDIA; > + } > + } > + > + if (Cdb->StatCode !=3D PXE_STATCODE_SUCCESS) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } else { > + Nic->State =3D PXE_STATFLAGS_GET_STATE_INITIALIZED; > + } > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > +} > + > +/** > + Initialize Network interface controller data. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in, out] Nic A pointer to the Network interface controller = data. > + > + @retval Status A value of Pxe statcode. > + > +**/ > +UINT16 > +Initialize ( > + IN PXE_CDB *Cdb, > + IN OUT NIC_DATA *Nic > + ) > +{ > + UINTN Status; > + UINT32 Index; > + EFI_STATUS EfiStatus; > + > + Status =3D MapIt ( > + Nic, > + Nic->PxeInit.MemoryAddr, > + Nic->PxeInit.MemoryLength, > + TO_AND_FROM_DEVICE, > + (UINT64)(UINTN)&Nic->MappedAddr > + ); > + > + if (Status !=3D 0) { > + return (UINT16)Status; > + } > + > + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { > + Nic->PermNodeAddress[Index] =3D Nic->MacAddr.Addr[Index]; > + } > + > + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { > + Nic->CurrentNodeAddress[Index] =3D Nic->PermNodeAddress[Index]; > + } > + > + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { > + Nic->BroadcastNodeAddress[Index] =3D 0xFF; > + } > + > + for (Index =3D PXE_HWADDR_LEN_ETHER; Index < PXE_MAC_LENGTH; Index++) = { > + Nic->CurrentNodeAddress[Index] =3D 0; > + Nic->PermNodeAddress[Index] =3D 0; > + Nic->BroadcastNodeAddress[Index] =3D 0; > + } > + > + if (Nic->UsbEth->UsbEthInitialize !=3D NULL) { > + EfiStatus =3D Nic->UsbEth->UsbEthInitialize (Cdb, Nic); > + if (EFI_ERROR (EfiStatus)) { > + return PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > + > + return (UINT16)Status; > +} > + > +/** > + This command resets the network adapter and reinitializes the UNDI > + with the same parameters provided in the Initialize command. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiReset ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_RESET) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || > + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || > + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || > + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + > + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { > + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + return; > + } > + > + if ((Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED) && > + (Cdb->OpFlags !=3D PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) && > + (Cdb->OpFlags !=3D PXE_OPFLAGS_RESET_DISABLE_FILTERS)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } > + > + if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_FILTERS) =3D=3D 0) { > + Nic->RxFilter =3D PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; > + } > + > + if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) !=3D 0) { > + Nic->InterrupOpFlag =3D 0; > + } > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReset !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiReset (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > +} > + > +/** > + The Shutdown command resets the network adapter and leaves it in a > + safe state for another driver to initialize. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in, out] Nic A pointer to the Network interface controller dat= a. > + > +**/ > +VOID > +UndiShutdown ( > + IN PXE_CDB *Cdb, > + IN OUT NIC_DATA *Nic > + ) > +{ > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_SHUTDOWN) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || > + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || > + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || > + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) || > + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + > + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { > + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + return; > + } > + > + Nic->CanTransmit =3D FALSE; > + > + Nic->State =3D PXE_STATFLAGS_GET_STATE_STARTED; > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > +} > + > +/** > + The Interrupt Enables command can be used to read and/or change > + the current external interrupt enable settings. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiInterruptEnable ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + EFI_STATUS Status; > + > + Cdb->StatCode =3D PXE_STATCODE_UNSUPPORTED; > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable (Cdb, N= ic); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + } > +} > + > +/** > + This command is used to read and change receive filters and, > + if supported, read and change the multicast MAC address filter list. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiReceiveFilter ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + UINT16 NewFilter; > + PXE_DB_RECEIVE_FILTERS *Db; > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_RECEIVE_FILTERS) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8))) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + > + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { > + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + return; > + } > + > + NewFilter =3D (UINT16)(Cdb->OpFlags & 0x1F); > + > + switch (Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_OPMASK) { > + case PXE_OPFLAGS_RECEIVE_FILTER_READ: > + if (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + } > + > + if ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) =3D= =3D 0) { > + if ((Cdb->DBsize !=3D 0)) { > + Db =3D (PXE_DB_RECEIVE_FILTERS *)(UINTN)Cdb->DBaddr; > + CopyMem (Db, &Nic->McastList, Nic->McastCount); > + } > + } > + > + break; > + > + case PXE_OPFLAGS_RECEIVE_FILTER_ENABLE: > + if (NewFilter =3D=3D 0) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + > + if (Cdb->CPBsize !=3D 0) { > + if (((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST)= =3D=3D 0) || > + ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != =3D 0) || > + ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) !=3D= 0) || > + ((Cdb->CPBsize % sizeof (PXE_MAC_ADDR)) !=3D 0)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > + > + if ((Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST)= !=3D 0) { > + if (((Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST= ) !=3D 0) || > + ((Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != =3D 0)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + > + if ((Cdb->CPBsize =3D=3D 0)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > + > + Cdb->StatCode =3D SetFilter (Nic, NewFilter, Cdb->CPBaddr, Cdb->CP= Bsize); > + break; > + > + case PXE_OPFLAGS_RECEIVE_FILTER_DISABLE: > + if (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + } > + > + break; > + > + default: > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + } > + > + Cdb->StatFlags =3D (PXE_STATFLAGS)(Cdb->StatFlags | Nic->RxFilter); > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter (Cdb, Nic= ); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > +} > + > +/** > + Set PXE receive filter. > + > + @param[in] Nic A pointer to the Network interface controller = data. > + @param[in] SetFilter PXE receive filter > + @param[in] CpbAddr Command Parameter Block Address > + @param[in] CpbSize Command Parameter Block Size > + > +**/ > +UINT16 > +SetFilter ( > + IN NIC_DATA *Nic, > + IN UINT16 SetFilter, > + IN UINT64 CpbAddr, > + IN UINT32 CpbSize > + ) > +{ > + EFI_STATUS Status; > + UINT8 *McastList; > + UINT8 Count; > + UINT8 Index1; > + UINT8 Index2; > + PXE_CPB_RECEIVE_FILTERS *Cpb; > + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; > + > + Count =3D 0; > + Cpb =3D (PXE_CPB_RECEIVE_FILTERS *)(UINTN)CpbAddr; > + > + // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED) > + Nic->RxFilter =3D (UINT8)SetFilter; > + > + if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) !=3D = 0) || (Cpb !=3D NULL)) { > + if (Cpb !=3D NULL) { > + Nic->McastCount =3D (UINT8)(CpbSize / PXE_MAC_LENGTH); > + CopyMem (&Nic->McastList, Cpb, Nic->McastCount); > + } > + > + Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth, &UsbEthFunDescriptor)= ; > + if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) { > + Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; > + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); > + } else { > + Status =3D gBS->AllocatePool (EfiBootServicesData, Nic->McastCount= * 6, (VOID **)&McastList); > + if (EFI_ERROR (Status)) { > + return PXE_STATCODE_INVALID_PARAMETER; > + } > + > + if (Cpb !=3D NULL) { > + for (Index1 =3D 0; Index1 < Nic->McastCount; Index1++) { > + for (Index2 =3D 0; Index2 < 6; Index2++) { > + McastList[Count++] =3D Cpb->MCastList[Index1][Index2]; > + } > + } > + } > + > + Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; > + if (Cpb !=3D NULL) { > + Nic->UsbEth->SetUsbEthMcastFilter (Nic->UsbEth, Nic->McastCount,= McastList); > + } > + > + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); > + FreePool (McastList); > + } > + } > + > + return PXE_STATCODE_SUCCESS; > +} > + > +/** > + This command is used to get current station and broadcast MAC addresse= s > + and, if supported, to change the current station MAC address. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiStationAddress ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + PXE_CPB_STATION_ADDRESS *Cpb; > + PXE_DB_STATION_ADDRESS *Db; > + UINT16 Index; > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_STATION_ADDRESS) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->DBsize !=3D sizeof (PXE_DB_STATION_ADDRESS))) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + > + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { > + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + return; > + } > + > + if (Cdb->OpFlags =3D=3D PXE_OPFLAGS_STATION_ADDRESS_RESET) { > + if (CompareMem (&Nic->CurrentNodeAddress[0], &Nic->PermNodeAddress[0= ], PXE_MAC_LENGTH) !=3D 0) { > + for (Index =3D 0; Index < PXE_MAC_LENGTH; Index++) { > + Nic->CurrentNodeAddress[Index] =3D Nic->PermNodeAddress[Index]; > + } > + } > + } > + > + if (Cdb->CPBaddr !=3D 0) { > + Cpb =3D (PXE_CPB_STATION_ADDRESS *)(UINTN)Cdb->CPBaddr; > + for (Index =3D 0; Index < PXE_MAC_LENGTH; Index++) { > + Nic->CurrentNodeAddress[Index] =3D Cpb->StationAddr[Index]; > + } > + } > + > + if (Cdb->DBaddr !=3D 0) { > + Db =3D (PXE_DB_STATION_ADDRESS *)(UINTN)Cdb->DBaddr; > + for (Index =3D 0; Index < PXE_MAC_LENGTH; Index++) { > + Db->StationAddr[Index] =3D Nic->CurrentNodeAddress[Index]; > + Db->BroadcastAddr[Index] =3D Nic->BroadcastNodeAddress[Index]; > + Db->PermanentAddr[Index] =3D Nic->PermNodeAddress[Index]; > + } > + } > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress (Cdb, Ni= c); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > +} > + > +/** > + This command is used to read and clear the NIC traffic statistics. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiStatistics ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_STATISTICS) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || > + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + } > + > + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { > + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + return; > + } > + > + if ((Cdb->OpFlags !=3D PXE_OPFLAGS_STATISTICS_RESET) && > + (Cdb->OpFlags !=3D PXE_OPFLAGS_STATISTICS_READ)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } > + > + Cdb->StatCode =3D Statistics (Nic, Cdb->DBaddr, Cdb->DBsize); > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > +} > + > +/** > + Return data for DB data. > + > + @param[in] Nic A pointer to the Network interface controller dat= a. > + @param[in] DbAddr Data Block Address. > + @param[in] DbSize Data Block Size. > + > +**/ > +UINT16 > +Statistics ( > + IN NIC_DATA *Nic, > + IN UINT64 DbAddr, > + IN UINT16 DbSize > + ) > +{ > + PXE_DB_STATISTICS *DbStatistic; > + EFI_STATUS Status; > + > + DbStatistic =3D (PXE_DB_STATISTICS *)(UINTN)DbAddr; > + > + if (DbSize =3D=3D 0) { > + return PXE_STATCODE_SUCCESS; > + } > + > + DbStatistic->Supported =3D 0x802; > + DbStatistic->Data[0x01] =3D Nic->RxFrame; > + DbStatistic->Data[0x0B] =3D Nic->TxFrame; > + > + if (Nic->UsbEth->UsbEthStatistics !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthStatistics (Nic, DbAddr, DbSize); > + if (EFI_ERROR (Status)) { > + return PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > + > + return PXE_STATCODE_SUCCESS; > +} > + > +/** > + Translate a multicast IPv4 or IPv6 address to a multicast MAC address. > + > + @param[in, out] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller dat= a. > + > +**/ > +VOID > +UndiMcastIp2Mac ( > + IN OUT PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + PXE_CPB_MCAST_IP_TO_MAC *Cpb; > + PXE_DB_MCAST_IP_TO_MAC *Db; > + UINT8 *Tmp; > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_MCAST_IP_TO_MAC) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->CPBsize !=3D sizeof (PXE_CPB_MCAST_IP_TO_MAC)) || > + (Cdb->DBsize !=3D sizeof (PXE_DB_MCAST_IP_TO_MAC))) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + > + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { > + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + return; > + } > + > + Cpb =3D (PXE_CPB_MCAST_IP_TO_MAC *)(UINTN)Cdb->CPBaddr; > + Db =3D (PXE_DB_MCAST_IP_TO_MAC *)(UINTN)Cdb->DBaddr; > + > + if ((Cdb->OpFlags & PXE_OPFLAGS_MCAST_IPV6_TO_MAC) !=3D 0) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_UNSUPPORTED; > + return; > + } > + > + Tmp =3D (UINT8 *)(&Cpb->IP.IPv4); > + > + if ((Tmp[0] & 0xF0) !=3D 0xE0) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CPB; > + } > + > + Db->MAC[0] =3D 0x01; > + Db->MAC[1] =3D 0x00; > + Db->MAC[2] =3D 0x5E; > + Db->MAC[3] =3D Tmp[1] & 0x7F; > + Db->MAC[4] =3D Tmp[2]; > + Db->MAC[5] =3D Tmp[3]; > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > +} > + > +/** > + This command is used to read and write (if supported by NIC H/W) > + nonvolatile storage on the NIC. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiNvData ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + EFI_STATUS Status; > + > + Cdb->StatCode =3D PXE_STATCODE_UNSUPPORTED; > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + } > +} > + > +/** > + This command returns the current interrupt status and/or the > + transmitted buffer addresses and the current media status. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiGetStatus ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + PXE_DB_GET_STATUS *Db; > + PXE_DB_GET_STATUS TmpGetStatus; > + UINT16 NumEntries; > + UINTN Index; > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_GET_STATUS) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || > + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + > + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { > + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + return; > + } > + > + TmpGetStatus.RxFrameLen =3D 0; > + TmpGetStatus.reserved =3D 0; > + Db =3D (PXE_DB_GET_STATUS *)(UINTN)Cdb->DBaddr; > + > + if ((Cdb->DBsize > 0) && (Cdb->DBsize < sizeof (UINT32) * 2)) { > + CopyMem (Db, &TmpGetStatus, Cdb->DBsize); > + } else { > + CopyMem (Db, &TmpGetStatus, sizeof (UINT32) * 2); > + } > + > + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS) !=3D 0) { > + if (Cdb->DBsize =3D=3D 0) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } > + > + NumEntries =3D Cdb->DBsize - sizeof (UINT64); > + Cdb->DBsize =3D sizeof (UINT32) * 2; > + > + for (Index =3D 0; NumEntries >=3D sizeof (UINT64); Index++, NumEntri= es -=3D sizeof (UINT64)) { > + if (Nic->TxBufferCount > 0) { > + Nic->TxBufferCount--; > + Db->TxBuffer[Index] =3D Nic->MediaHeader[Nic->TxBufferCount]; > + } > + } > + } > + > + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_INTERRUPT_STATUS) !=3D 0) { > + if (Nic->ReceiveStatus !=3D 0) { > + Cdb->StatFlags |=3D PXE_STATFLAGS_GET_STATUS_RECEIVE; > + } > + } > + > + if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTION) && (Nic->= Request.Value =3D=3D NETWORK_DISCONNECT)) { > + Nic->CableDetect =3D 0; > + } else if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTION) &&= (Nic->Request.Value =3D=3D NETWORK_CONNECTED)) { > + Nic->CableDetect =3D 1; > + } > + > + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_MEDIA_STATUS) !=3D 0) { > + if (Nic->CableDetect =3D=3D 0) { > + Cdb->StatFlags |=3D PXE_STATFLAGS_GET_STATUS_NO_MEDIA; > + } > + } > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > +} > + > +/** > + This command is used to fill the media header(s) in transmit packet(s)= . > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiFillHeader ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + PXE_CPB_FILL_HEADER *CpbFillHeader; > + PXE_CPB_FILL_HEADER_FRAGMENTED *CpbFill; > + EthernetHeader *MacHeader; > + UINTN Index; > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_FILL_HEADER) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->CPBsize !=3D sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED)) || > + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || > + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + > + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { > + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + return; > + } > + > + if (Cdb->CPBsize =3D=3D PXE_CPBSIZE_NOT_USED) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } > + > + if ((Cdb->OpFlags & PXE_OPFLAGS_FILL_HEADER_FRAGMENTED) !=3D 0) { > + CpbFill =3D (PXE_CPB_FILL_HEADER_FRAGMENTED *)(UINTN)Cdb->CPBaddr; > + > + if ((CpbFill->FragCnt =3D=3D 0) || (CpbFill->FragDesc[0].FragLen < P= XE_MAC_HEADER_LEN_ETHER)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } > + > + MacHeader =3D (EthernetHeader *)(UINTN)CpbFill->FragDesc[0= ].FragAddr; > + MacHeader->Protocol =3D CpbFill->Protocol; > + > + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { > + MacHeader->DestAddr[Index] =3D CpbFill->DestAddr[Index]; > + MacHeader->SrcAddr[Index] =3D CpbFill->SrcAddr[Index]; > + } > + } else { > + CpbFillHeader =3D (PXE_CPB_FILL_HEADER *)(UINTN)Cdb->CPBaddr; > + > + MacHeader =3D (EthernetHeader *)(UINTN)CpbFillHeader->Medi= aHeader; > + MacHeader->Protocol =3D CpbFillHeader->Protocol; > + > + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { > + MacHeader->DestAddr[Index] =3D CpbFillHeader->DestAddr[Index]; > + MacHeader->SrcAddr[Index] =3D CpbFillHeader->SrcAddr[Index]; > + } > + } > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + } > +} > + > +/** > + The Transmit command is used to place a packet into the transmit queue= . > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiTransmit ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_TRANSMIT) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->CPBsize !=3D sizeof (PXE_CPB_TRANSMIT)) || > + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || > + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + > + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; > + return; > + } > + > + if (Cdb->CPBsize =3D=3D PXE_CPBSIZE_NOT_USED) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + > + return; > + } > + > + Cdb->StatCode =3D Transmit (Cdb, Nic, Cdb->CPBaddr, Cdb->OpFlags); > + > + if (Cdb->StatCode !=3D PXE_STATCODE_SUCCESS) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > +} > + > +/** > + Use USB Ethernet Protocol Bulk out command to transmit data. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in, out] Nic A pointer to the Network interface controller= data. > + @param[in] CpbAddr Command Parameter Block Address. > + @param[in] OpFlags Operation Flags. > + > +**/ > +UINT16 > +Transmit ( > + IN PXE_CDB *Cdb, > + IN OUT NIC_DATA *Nic, > + IN UINT64 CpbAddr, > + IN UINT16 OpFlags > + ) > +{ > + EFI_STATUS Status; > + PXE_CPB_TRANSMIT *Cpb; > + UINT64 BulkOutData; > + UINTN DataLength; > + UINTN TransmitLength; > + UINTN Map; > + UINT32 Counter; > + UINT16 StatCode; > + > + BulkOutData =3D 0; > + Counter =3D 0; > + Cpb =3D (PXE_CPB_TRANSMIT *)(UINTN)CpbAddr; > + > + if (Nic->CanTransmit) { > + return PXE_STATCODE_BUSY; > + } > + > + Nic->CanTransmit =3D TRUE; > + > + if ((OpFlags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) !=3D 0) { > + return PXE_STATCODE_INVALID_PARAMETER; > + } > + > + Map =3D MapIt ( > + Nic, > + Cpb->FrameAddr, > + Cpb->DataLen + (UINT32)Cpb->MediaheaderLen, > + TO_DEVICE, > + (UINT64)(UINTN)&BulkOutData > + ); > + > + if (Map !=3D 0) { > + Nic->CanTransmit =3D FALSE; > + return PXE_STATCODE_INVALID_PARAMETER; > + } > + > + if (Nic->TxBufferCount < MAX_XMIT_BUFFERS) { > + Nic->MediaHeader[Nic->TxBufferCount] =3D Cpb->FrameAddr; > + Nic->TxBufferCount++; > + } > + > + DataLength =3D (UINTN)(Cpb->DataLen + (UINT32)Cpb->MediaheaderLen); > + > + while (1) { > + if (Counter >=3D 3) { > + StatCode =3D PXE_STATCODE_BUSY; > + break; > + } > + > + TransmitLength =3D DataLength; > + > + Status =3D Nic->UsbEth->UsbEthTransmit (Cdb, Nic->UsbEth, (VOID *)(U= INTN)BulkOutData, &TransmitLength); > + if (EFI_ERROR (Status)) { > + StatCode =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + > + if (Status =3D=3D EFI_INVALID_PARAMETER) { > + StatCode =3D PXE_STATCODE_INVALID_PARAMETER; > + break; > + } > + > + if (Status =3D=3D EFI_DEVICE_ERROR) { > + StatCode =3D PXE_STATCODE_DEVICE_FAILURE; > + break; > + } > + > + if (!EFI_ERROR (Status)) { > + Nic->TxFrame++; > + StatCode =3D PXE_STATCODE_SUCCESS; > + break; > + } > + > + Counter++; > + } > + > + UnMapIt ( > + Nic, > + Cpb->FrameAddr, > + Cpb->DataLen + (UINT32)Cpb->MediaheaderLen, > + TO_DEVICE, > + BulkOutData > + ); > + > + Nic->CanTransmit =3D FALSE; > + > + return StatCode; > +} > + > +/** > + When the network adapter has received a frame, this command is used > + to copy the frame into driver/application storage. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > +**/ > +VOID > +UndiReceive ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + EFI_STATUS Status; > + > + if ((Cdb->OpCode !=3D PXE_OPCODE_RECEIVE) || > + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || > + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || > + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || > + (Cdb->CPBsize !=3D sizeof (PXE_CPB_RECEIVE)) || > + (Cdb->DBsize !=3D sizeof (PXE_DB_RECEIVE)) || > + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) > + { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; > + return; > + } else { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; > + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; > + } > + > + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; > + return; > + } > + > + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive !=3D NULL) { > + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > + > + return; > + } > + > + Cdb->StatCode =3D Receive (Cdb, Nic, Cdb->CPBaddr, Cdb->DBaddr); > + > + if (Cdb->StatCode !=3D PXE_STATCODE_SUCCESS) { > + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; > + } > +} > + > +/** > + Use USB Ethernet Protocol Bulk in command to receive data. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in, out] Nic A pointer to the Network interface controller= data. > + @param[in] CpbAddr Command Parameter Block Address. > + @param[in, out] DbAddr Data Block Address. > + > +**/ > +UINT16 > +Receive ( > + IN PXE_CDB *Cdb, > + IN OUT NIC_DATA *Nic, > + IN UINT64 CpbAddr, > + IN OUT UINT64 DbAddr > + ) > +{ > + EFI_STATUS Status; > + UINTN Index; > + PXE_FRAME_TYPE FrameType; > + PXE_CPB_RECEIVE *Cpb; > + PXE_DB_RECEIVE *Db; > + NIC_DEVICE *NicDevice; > + UINT8 *BulkInData; > + UINTN DataLength; > + EthernetHeader *Header; > + EFI_TPL OriginalTpl; > + > + FrameType =3D PXE_FRAME_TYPE_NONE; > + NicDevice =3D UNDI_DEV_FROM_NIC (Nic); > + BulkInData =3D NicDevice->ReceiveBuffer; > + DataLength =3D (UINTN)Nic->MaxSegmentSize; > + Cpb =3D (PXE_CPB_RECEIVE *)(UINTN)CpbAddr; > + Db =3D (PXE_DB_RECEIVE *)(UINTN)DbAddr; > + > + if (!BulkInData) { > + return PXE_STATCODE_INVALID_PARAMETER; > + } > + > + if ((Nic->RateLimitingCreditCount =3D=3D 0) && (Nic->RateLimitingEnabl= e =3D=3D TRUE)) { > + return PXE_STATCODE_NO_DATA; > + } > + > + Status =3D Nic->UsbEth->UsbEthReceive (Cdb, Nic->UsbEth, (VOID *)BulkI= nData, &DataLength); > + if (EFI_ERROR (Status)) { > + Nic->ReceiveStatus =3D 0; > + if (Nic->RateLimitingEnable =3D=3D TRUE) { > + OriginalTpl =3D gBS->RaiseTPL (TPL_NOTIFY); > + if (Nic->RateLimitingCreditCount !=3D 0) { > + Nic->RateLimitingCreditCount--; > + } > + > + gBS->RestoreTPL (OriginalTpl); > + } > + > + return PXE_STATCODE_NO_DATA; > + } > + > + Nic->RxFrame++; > + > + if (DataLength !=3D 0) { > + if (DataLength > Cpb->BufferLen) { > + DataLength =3D (UINTN)Cpb->BufferLen; > + } > + > + CopyMem ((UINT8 *)(UINTN)Cpb->BufferAddr, (UINT8 *)BulkInData, DataL= ength); > + > + Header =3D (EthernetHeader *)BulkInData; > + > + Db->FrameLen =3D (UINT32)DataLength; > + Db->MediaHeaderLen =3D PXE_MAC_HEADER_LEN_ETHER; > + > + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { > + if (Header->DestAddr[Index] !=3D Nic->CurrentNodeAddress[Index]) { > + break; > + } > + } > + > + if (Index >=3D PXE_HWADDR_LEN_ETHER) { > + FrameType =3D PXE_FRAME_TYPE_UNICAST; > + } else { > + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { > + if (Header->DestAddr[Index] !=3D Nic->BroadcastNodeAddress[Index= ]) { > + break; > + } > + } > + > + if (Index >=3D PXE_HWADDR_LEN_ETHER) { > + FrameType =3D PXE_FRAME_TYPE_BROADCAST; > + } else { > + if ((Header->DestAddr[0] & 1) =3D=3D 1) { > + FrameType =3D PXE_FRAME_TYPE_FILTERED_MULTICAST; > + } else { > + FrameType =3D PXE_FRAME_TYPE_PROMISCUOUS; > + } > + } > + } > + > + Db->Type =3D FrameType; > + Db->Protocol =3D Header->Protocol; > + > + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { > + Db->SrcAddr[Index] =3D Header->SrcAddr[Index]; > + Db->DestAddr[Index] =3D Header->DestAddr[Index]; > + } > + } > + > + if (FrameType =3D=3D PXE_FRAME_TYPE_NONE) { > + Nic->ReceiveStatus =3D 0; > + } else { > + Nic->ReceiveStatus =3D 1; > + } > + > + return PXE_STATCODE_SUCCESS; > +} > + > +/** > + Fill out PXE SW UNDI structure. > + > + @param[out] PxeSw A pointer to the PXE SW UNDI structure. > + > +**/ > +VOID > +PxeStructInit ( > + OUT PXE_SW_UNDI *PxeSw > + ) > +{ > + PxeSw->Signature =3D PXE_ROMID_SIGNATURE; > + PxeSw->Len =3D (UINT8)sizeof (PXE_SW_UNDI); > + PxeSw->Fudge =3D 0; > + PxeSw->IFcnt =3D 0; > + PxeSw->IFcntExt =3D 0; > + PxeSw->Rev =3D PXE_ROMID_REV; > + PxeSw->MajorVer =3D PXE_ROMID_MAJORVER; > + PxeSw->MinorVer =3D PXE_ROMID_MINORVER; > + PxeSw->reserved1 =3D 0; > + > + PxeSw->Implementation =3D PXE_ROMID_IMP_SW_VIRT_ADDR | > + PXE_ROMID_IMP_FRAG_SUPPORTED | > + PXE_ROMID_IMP_CMD_LINK_SUPPORTED | > + PXE_ROMID_IMP_STATION_ADDR_SETTABLE | > + PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORT= ED | > + PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED | > + PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED | > + PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED; > + > + PxeSw->EntryPoint =3D (UINT64)(UINTN)UndiApiEntry; > + PxeSw->reserved2[0] =3D 0; > + PxeSw->reserved2[1] =3D 0; > + PxeSw->reserved2[2] =3D 0; > + PxeSw->BusCnt =3D 1; > + PxeSw->BusType[0] =3D PXE_BUSTYPE_USB; > + PxeSw->Fudge =3D PxeSw->Fudge - CalculateSum8 ((VOID *)PxeSw, P= xeSw->Len); > +} > + > +/** > + Update NIC number. > + > + @param[in] Nic A pointer to the Network interface controlle= r data. > + @param[in, out] PxeSw A pointer to the PXE SW UNDI structure. > + > +**/ > +VOID > +UpdateNicNum ( > + IN NIC_DATA *Nic, > + IN OUT PXE_SW_UNDI *PxeSw > + ) > +{ > + UINT16 NicNum; > + > + NicNum =3D (PxeSw->IFcnt | PxeSw->IFcntExt << 8); > + > + if (Nic =3D=3D NULL) { > + if (NicNum > 0) { > + NicNum--; > + } > + > + PxeSw->IFcnt =3D (UINT8)(NicNum & 0xFF); // Get lower by= te > + PxeSw->IFcntExt =3D (UINT8)((NicNum & 0xFF00) >> 8); // Get upper by= te > + PxeSw->Fudge =3D (UINT8)(PxeSw->Fudge - CalculateSum8 ((VOID *)Px= eSw, PxeSw->Len)); > + return; > + } > + > + NicNum++; > + > + PxeSw->IFcnt =3D (UINT8)(NicNum & 0xFF); // Get lower byte > + PxeSw->IFcntExt =3D (UINT8)((NicNum & 0xFF00) >> 8); // Get upper byte > + PxeSw->Fudge =3D (UINT8)(PxeSw->Fudge - CalculateSum8 ((VOID *)PxeS= w, PxeSw->Len)); > +} > + > +/** > + UNDI API table entry. > + > + @param[in] Cdb A pointer to the command descriptor block. > + > +**/ > +EFI_STATUS > +EFIAPI > +UndiApiEntry ( > + IN UINT64 Cdb > + ) > +{ > + PXE_CDB *CdbPtr; > + NIC_DATA *Nic; > + > + if (Cdb =3D=3D 0) { > + return EFI_INVALID_PARAMETER; > + } > + > + CdbPtr =3D (PXE_CDB *)(UINTN)Cdb; > + Nic =3D &(gLanDeviceList[CdbPtr->IFnum]->NicInfo); > + gUndiApiTable[CdbPtr->OpCode](CdbPtr, Nic); > + return EFI_SUCCESS; > +} > + > +/** > + Map virtual memory address for DMA. This field can be set to > + zero if there is no mapping service. > + > + @param[in] Nic A pointer to the Network interface controlle= r data. > + @param[in] MemAddr Virtual address to be mapped. > + @param[in] Size Size of memory to be mapped. > + @param[in] Direction Direction of data flow for this memory's usa= ge: > + cpu->device, device->cpu or both ways. > + @param[out] MappedAddr Pointer to return the mapped device address. > + > +**/ > +UINTN > +MapIt ( > + IN NIC_DATA *Nic, > + IN UINT64 MemAddr, > + IN UINT32 Size, > + IN UINT32 Direction, > + OUT UINT64 MappedAddr > + ) > +{ > + UINT64 *PhyAddr; > + > + PhyAddr =3D (UINT64 *)(UINTN)MappedAddr; > + > + if (Nic->PxeStart.Map_Mem =3D=3D 0) { > + *PhyAddr =3D MemAddr; > + } else { > + ((void (*)(UINT64, UINT64, UINT32, UINT32, UINT64))(UINTN) Nic->PxeS= tart.Map_Mem)( > + Nic->PxeStart.Unique_ID, > + MemAddr, > + Size, > + Direction, > + MappedAddr > + ); > + } > + > + return PXE_STATCODE_SUCCESS; > +} > + > +/** > + Un-map previously mapped virtual memory address. This field can be set > + to zero only if the Map_Mem() service is also set to zero. > + > + @param[in] Nic A pointer to the Network interface controlle= r data. > + @param[in] MemAddr Virtual address to be mapped. > + @param[in] Size Size of memory to be mapped. > + @param[in] Direction Direction of data flow for this memory's usa= ge: > + cpu->device, device->cpu or both ways. > + @param[in] MappedAddr Pointer to return the mapped device address. > + > +**/ > +VOID > +UnMapIt ( > + IN NIC_DATA *Nic, > + IN UINT64 MemAddr, > + IN UINT32 Size, > + IN UINT32 Direction, > + IN UINT64 MappedAddr > + ) > +{ > + if (Nic->PxeStart.UnMap_Mem !=3D 0) { > + ((void (*)(UINT64, UINT64, UINT32, UINT32, UINT64))(UINTN) Nic->PxeS= tart.UnMap_Mem)( > + Nic->PxeStart.Unique_ID, > + MemAddr, > + Size, > + Direction, > + MappedAddr > + ); > + } > + > + return; > +} > diff --git a/UsbNetworkPkg/UsbRndis/ComponentName.c b/UsbNetworkPkg/UsbRn= dis/ComponentName.c > new file mode 100644 > index 000000000000..b9ba170c135b > --- /dev/null > +++ b/UsbNetworkPkg/UsbRndis/ComponentName.c > @@ -0,0 +1,172 @@ > +/** @file > + This file contains code for USB RNDIS Driver Component > + Name definitions > + > + Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#include "UsbRndis.h" > + > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE gUsbRndisDriverN= ameTable[] =3D { > + { > + "eng;en", > + L"USB RNDIS Driver" > + }, > + { > + NULL, > + NULL > + } > +}; > + > +EFI_STATUS > +EFIAPI > +UsbRndisComponentNameGetDriverName ( > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > + IN CHAR8 *Language, > + OUT CHAR16 **DriverName > + ); > + > +EFI_STATUS > +EFIAPI > +UsbRndisComponentNameGetControllerName ( > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > + IN EFI_HANDLE Controller, > + IN EFI_HANDLE ChildHandle OPTIONAL, > + IN CHAR8 *Language, > + OUT CHAR16 **ControllerName > + ); > + > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gUsbRndisComp= onentName =3D { > + UsbRndisComponentNameGetDriverName, > + UsbRndisComponentNameGetControllerName, > + "eng" > +}; > + > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gUsbRndisCom= ponentName2 =3D { > + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbRndisComponentNameGetDriverNam= e, > + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbRndisComponentNameGetContr= ollerName, > + "en" > +}; > + > +/** > + Retrieves a Unicode string that is the user readable name of the drive= r. > + > + This function retrieves the user readable name of a driver in the form= of a > + Unicode string. If the driver specified by This has a user readable na= me in > + the language specified by Language, then a pointer to the driver name = is > + returned in DriverName, and EFI_SUCCESS is returned. If the driver spe= cified > + by This does not support the language specified by Language, > + then EFI_UNSUPPORTED is returned. > + > + @param[in] This A pointer to the EFI_COMPONENT_NAME2_PRO= TOCOL or > + EFI_COMPONENT_NAME_PROTOCOL instance. > + @param[in] Language A pointer to a Null-terminated ASCII str= ing > + array indicating the language. This is t= he > + language of the driver name that the cal= ler is > + requesting, and it must match one of the > + languages specified in SupportedLanguage= s. The > + number of languages supported by a drive= r is up > + to the driver writer. Language is specif= ied > + in RFC 4646 or ISO 639-2 language code f= ormat. > + @param[out] DriverName A pointer to the Unicode string to retur= n. > + This Unicode string is the name of the > + driver specified by This in the language > + specified by Language. > + > + @retval EFI_SUCCESS The Unicode string for the Driver specif= ied by > + This and the language specified by Langu= age was > + returned in DriverName. > + @retval EFI_INVALID_PARAMETER Language is NULL. > + @retval EFI_INVALID_PARAMETER DriverName is NULL. > + @retval EFI_UNSUPPORTED The driver specified by This does not su= pport > + the language specified by Language. > + > +**/ > +EFI_STATUS > +EFIAPI > +UsbRndisComponentNameGetDriverName ( > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > + IN CHAR8 *Language, > + OUT CHAR16 **DriverName > + ) > +{ > + return LookupUnicodeString2 ( > + Language, > + This->SupportedLanguages, > + gUsbRndisDriverNameTable, > + DriverName, > + (BOOLEAN)(This =3D=3D &gUsbRndisComponentName) > + ); > +} > + > +/** > + Retrieves a Unicode string that is the user readable name of the contr= oller > + that is being managed by a driver. > + > + This function retrieves the user readable name of the controller speci= fied by > + ControllerHandle and ChildHandle in the form of a Unicode string. If t= he > + driver specified by This has a user readable name in the language spec= ified by > + Language, then a pointer to the controller name is returned in Control= lerName, > + and EFI_SUCCESS is returned. If the driver specified by This is not c= urrently > + managing the controller specified by ControllerHandle and ChildHandle, > + then EFI_UNSUPPORTED is returned. If the driver specified by This doe= s not > + support the language specified by Language, then EFI_UNSUPPORTED is re= turned. > + > + @param[in] This A pointer to the EFI_COMPONENT_NAME2_PRO= TOCOL or > + EFI_COMPONENT_NAME_PROTOCOL instance. > + @param[in] Controller The handle of a controller that the driv= er > + specified by This is managing. This han= dle > + specifies the controller whose name is t= o be > + returned. > + @param[in] ChildHandle The handle of the child controller to re= trieve > + the name of. This is an optional parame= ter 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 bu= s > + controller. It will not be NULL for a b= us > + driver that wishes to retrieve the name = of a > + child controller. > + @param[in] Language A pointer to a Null-terminated ASCII str= ing > + array indicating the language. This is = the > + language of the driver name that the cal= ler is > + requesting, and it must match one of the > + languages specified in SupportedLanguage= s. The > + number of languages supported by a drive= r is up > + to the driver writer. Language is specif= ied in > + RFC 4646 or ISO 639-2 language code form= at. > + @param[out] ControllerName A pointer to the Unicode string to retur= n. > + 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 d= river > + specified by This. > + > + @retval EFI_SUCCESS The Unicode string for the user readable= name in > + the language specified by Language for t= he > + driver specified by This was returned in > + DriverName. > + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HAND= LE. > + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a = valid > + EFI_HANDLE. > + @retval EFI_INVALID_PARAMETER Language is NULL. > + @retval EFI_INVALID_PARAMETER ControllerName is NULL. > + @retval EFI_UNSUPPORTED The driver specified by This is not curr= ently > + managing the controller specified by > + ControllerHandle and ChildHandle. > + @retval EFI_UNSUPPORTED The driver specified by This does not su= pport > + the language specified by Language. > + > +**/ > +EFI_STATUS > +EFIAPI > +UsbRndisComponentNameGetControllerName ( > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > + IN EFI_HANDLE Controller, > + IN EFI_HANDLE ChildHandle OPTIONAL, > + IN CHAR8 *Language, > + OUT CHAR16 **ControllerName > + ) > +{ > + return EFI_UNSUPPORTED; > +} > diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.c b/UsbNetworkPkg/UsbRndis/U= sbRndis.c > new file mode 100644 > index 000000000000..92830771e408 > --- /dev/null > +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.c > @@ -0,0 +1,886 @@ > +/** @file > + This file contains code for USB Remote Network Driver > + Interface Spec. Driver Binding > + > + Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#include "UsbRndis.h" > + > +EFI_DRIVER_BINDING_PROTOCOL gUsbRndisDriverBinding =3D { > + UsbRndisDriverSupported, > + UsbRndisDriverStart, > + UsbRndisDriverStop, > + USB_RNDIS_DRIVER_VERSION, > + NULL, > + NULL > +}; > + > +/** > + Check if this interface is USB Rndis SubType > + > + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. > + > + @retval TRUE USB Rndis SubType. > + @retval FALSE Not USB Rndis SubType. > + > +**/ > +BOOLEAN > +IsSupportedDevice ( > + IN EFI_USB_IO_PROTOCOL *UsbIo > + ) > +{ > + EFI_STATUS Status; > + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; > + > + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescript= or); > + if (EFI_ERROR (Status)) { > + return FALSE; > + } > + > + // Check specific device/RNDIS and CDC-DATA > + if (((InterfaceDescriptor.InterfaceClass =3D=3D 0x2) && > + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x2) && > + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0xFF)) || \ > + ((InterfaceDescriptor.InterfaceClass =3D=3D 0xEF) && > + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x4) && > + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0x1)) || \ > + ((InterfaceDescriptor.InterfaceClass =3D=3D 0xA) && > + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x0) && > + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0x00)) > + ) > + { > + return TRUE; > + } > + > + return FALSE; > +} > + > +/** > + Check if this interface is USB Rndis SubType but not CDC Data interfac= e > + > + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. > + > + @retval TRUE USB Rndis SubType. > + @retval FALSE Not USB Rndis SubType. > +**/ > +BOOLEAN > +IsRndisInterface ( > + IN EFI_USB_IO_PROTOCOL *UsbIo > + ) > +{ > + EFI_STATUS Status; > + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; > + > + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescript= or); > + if (EFI_ERROR (Status)) { > + return FALSE; > + } > + > + // Check for specific device/RNDIS and CDC-DATA > + if (((InterfaceDescriptor.InterfaceClass =3D=3D 0x2) && > + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x2) && > + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0xFF)) || \ > + ((InterfaceDescriptor.InterfaceClass =3D=3D 0xEF) && > + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x4) && > + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0x1)) > + ) > + { > + return TRUE; > + } > + > + return FALSE; > +} > + > +/** > + Check if the USB RNDIS and USB CDC Data interfaces are from the same d= evice. > + > + @param[in] UsbRndisDataPath A pointer to the EFI_DEVICE_PATH_PROTOCO= L instance. > + @param[in] UsbCdcDataPath A pointer to the EFI_DEVICE_PATH_PROTOCO= L instance. > + > + @retval EFI_SUCCESS Is the same device. > + @retval EFI_UNSUPPORTED Is not the same device. > + > +**/ > +EFI_STATUS > +IsSameDevice ( > + IN EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath, > + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath > + ) > +{ > + DEBUG ((DEBUG_VERBOSE, "IsSameDevice Entry \n")); > + while (1) { > + if (IsDevicePathEnd (NextDevicePathNode (UsbRndisDataPath))) { > + if (((USB_DEVICE_PATH *)UsbRndisDataPath)->ParentPortNumber =3D=3D > + ((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber) > + { > + return EFI_SUCCESS; > + } else { > + return EFI_UNSUPPORTED; > + } > + } else { > + if (CompareMem (UsbCdcDataPath, UsbRndisDataPath, sizeof (EFI_DEVI= CE_PATH_PROTOCOL)) !=3D 0) { > + return EFI_UNSUPPORTED; > + } > + > + UsbRndisDataPath =3D NextDevicePathNode (UsbRndisDataPath); > + UsbCdcDataPath =3D NextDevicePathNode (UsbCdcDataPath); > + } > + } > + > + DEBUG ((DEBUG_VERBOSE, "IsSameDevice Exit \n")); > +} > + > +/** > + Check if the USB CDC Data(UsbIo) installed and return USB CDC Data Han= dle. > + > + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. > + > + @retval TRUE USB CDC Data(UsbIo) installed. > + @retval FALSE USB CDC Data(UsbIo) did not installed. > + > +**/ > +BOOLEAN > +IsUsbCdcData ( > + IN EFI_USB_IO_PROTOCOL *UsbIo > + ) > +{ > + EFI_STATUS Status; > + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; > + > + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescript= or); > + if (EFI_ERROR (Status)) { > + return FALSE; > + } > + > + // Check for CDC-DATA > + if ((InterfaceDescriptor.InterfaceClass =3D=3D 0xA) && > + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x0) && > + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0x0)) > + { > + return TRUE; > + } > + > + return FALSE; > +} > + > +/** > + Check if the USB Rndis(UsbIo) installed > + > + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance= . > + > + @retval TRUE USB Rndis(UsbIo) installed. > + @retval FALSE USB Rndis(UsbIo) did not installed. > + > +**/ > +BOOLEAN > +IsUsbRndis ( > + IN EFI_USB_IO_PROTOCOL *UsbIo > + ) > +{ > + EFI_STATUS Status; > + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; > + > + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescript= or); > + if (EFI_ERROR (Status)) { > + return FALSE; > + } > + > + // Check for Rndis > + if ((InterfaceDescriptor.InterfaceClass =3D=3D 0x2) && > + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x2) && > + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0xFF)) > + { > + return TRUE; > + } > + > + return FALSE; > +} > + > +/** > + Control comes here when a CDC device is found.Check if a RNDIS interfa= ce is already found for this device or not. > + For one device two USBIO will be installed each for CDC and RNDIS inte= rface. > + > + @param[in] UsbEthPath A pointer to the EFI_DEVICE_PATH_PROTOCO= L instance. > + @param[out] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE Data. > + > + @retval EFI_SUCCESS The USB_RNDIS_DEVICE matching this CDC= Data is found. > + @retval EFI_NOT_FOUND The USB_RNDIS_DEVICE matching this CDC= Data is not found. > + > +**/ > +EFI_STATUS > +UpdateRndisDevice ( > + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath, > + OUT USB_RNDIS_DEVICE **UsbRndisDevice > + ) > +{ > + EFI_STATUS Status; > + UINTN Index; > + UINTN HandleCount; > + EFI_HANDLE *HandleBuffer; > + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDevice; > + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath; > + EFI_USB_IO_PROTOCOL *UsbIo; > + BOOLEAN IsRndisInterfaceFlag; > + > + IsRndisInterfaceFlag =3D FALSE; > + > + Status =3D gBS->LocateHandleBuffer ( > + ByProtocol, > + &gEdkIIUsbEthProtocolGuid, > + NULL, > + &HandleCount, > + &HandleBuffer > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + for (Index =3D 0; Index < HandleCount; Index++) { > + Status =3D gBS->HandleProtocol ( > + HandleBuffer[Index], > + &gEdkIIUsbEthProtocolGuid, > + (VOID **)&UsbEthDevice > + ); > + if (EFI_ERROR (Status)) { > + continue; > + } > + > + Status =3D gBS->HandleProtocol ( > + HandleBuffer[Index], > + &gEfiUsbIoProtocolGuid, > + (VOID **)&UsbIo > + ); > + if (EFI_ERROR (Status)) { > + continue; > + } > + > + IsRndisInterfaceFlag =3D IsRndisInterface (UsbIo); > + if (IsRndisInterfaceFlag =3D=3D FALSE) { > + continue; > + } > + > + Status =3D gBS->HandleProtocol ( > + HandleBuffer[Index], > + &gEfiDevicePathProtocolGuid, > + (VOID **)&UsbRndisDataPath > + ); > + if (EFI_ERROR (Status)) { > + continue; > + } > + > + Status =3D IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); > + > + DEBUG ((DEBUG_VERBOSE, "Rndis IsSameDevice %r\n", Status)); > + > + if (!EFI_ERROR (Status)) { > + *UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthDevice); > + FreePool (HandleBuffer); > + return EFI_SUCCESS; > + } > + } // End of For loop > + > + FreePool (HandleBuffer); > + return EFI_NOT_FOUND; > +} > + > +/** > + > + For the given Rndis Device, find a matching CDC device already exists = or not. If found update the handle > + and UsbIO protocol. > + > + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE da= ta. > + > +**/ > +VOID > +FindMatchingCdcData ( > + IN USB_RNDIS_DEVICE *UsbRndisDevice > + ) > +{ > + EFI_STATUS Status; > + UINTN Index; > + UINTN HandleCount; > + EFI_HANDLE *HandleBuffer; > + EFI_USB_IO_PROTOCOL *UsbIo; > + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath; > + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath; > + > + // Find the parent RNDIS and update the UsbIo for the CDC device > + Status =3D gBS->HandleProtocol ( > + UsbRndisDevice->UsbRndisHandle, > + &gEfiDevicePathProtocolGuid, > + (VOID **)&UsbRndisDataPath > + ); > + > + if (EFI_ERROR (Status)) { > + return; > + } > + > + Status =3D gBS->LocateHandleBuffer ( > + ByProtocol, > + &gEfiUsbIoProtocolGuid, > + NULL, > + &HandleCount, > + &HandleBuffer > + ); > + if (EFI_ERROR (Status)) { > + return; > + } > + > + for (Index =3D 0; Index < HandleCount; Index++) { > + Status =3D gBS->HandleProtocol ( > + HandleBuffer[Index], > + &gEfiUsbIoProtocolGuid, > + (VOID **)&UsbIo > + ); > + ASSERT_EFI_ERROR (Status); > + > + if (IsUsbCdcData (UsbIo)) { > + DEBUG ((DEBUG_VERBOSE, "Rndis FindMatchingCdcData CDCData interfac= e found\n")); > + > + Status =3D gBS->HandleProtocol ( > + HandleBuffer[Index], > + &gEfiDevicePathProtocolGuid, > + (VOID **)&UsbCdcDataPath > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "Rndis CDCData DevicePath not found\n")); > + FreePool (HandleBuffer); > + return; > + } > + > + Status =3D IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); > + DEBUG ((DEBUG_VERBOSE, "Rndis IsSameDevice %r\n", Status)); > + if (!EFI_ERROR (Status)) { > + UsbRndisDevice->UsbCdcDataHandle =3D HandleBuffer[Index]; > + UsbRndisDevice->UsbIoCdcData =3D UsbIo; > + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); > + FreePool (HandleBuffer); > + return; > + } > + } > + } // End of For loop > + > + FreePool (HandleBuffer); > +} > + > +/** > + > + For the given UsbIo CdcData, find a matching RNDIS device already exis= ts or not. > + > + @param[in] CdcHandle A pointer to the EFI_HANDLE for USB CDC Da= ta. > + @param[out] CdcUsbIo A pointer for retrieve the EFI_USB_IO_PROT= OCOL instance. > + @param[out] RndisHandle A pointer for retrieve the handle of RNDIS= device. > + > + @retval EFI_SUCCESS The USB_RNDIS_DEVICE matching this CDC= Data is found. > + @retval EFI_NOT_FOUND The USB_RNDIS_DEVICE matching this CDC= Data is not found. > + > +**/ > +EFI_STATUS > +EFIAPI > +FindMatchingRndisDev ( > + IN EFI_HANDLE CdcHandle, > + OUT EFI_USB_IO_PROTOCOL **CdcUsbIo, > + OUT EFI_HANDLE *RndisHandle > + ) > +{ > + EFI_STATUS Status; > + UINTN Index; > + UINTN HandleCount; > + EFI_HANDLE *HandleBuffer; > + EFI_USB_IO_PROTOCOL *UsbIo; > + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath; > + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath; > + > + // Find the parent RNDIS and update the UsbIo for the CDC device > + Status =3D gBS->HandleProtocol ( > + CdcHandle, > + &gEfiDevicePathProtocolGuid, > + (VOID **)&UsbCdcDataPath > + ); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D gBS->LocateHandleBuffer ( > + ByProtocol, > + &gEfiUsbIoProtocolGuid, > + NULL, > + &HandleCount, > + &HandleBuffer > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + for (Index =3D 0; Index < HandleCount; Index++) { > + Status =3D gBS->HandleProtocol ( > + HandleBuffer[Index], > + &gEfiUsbIoProtocolGuid, > + (VOID **)&UsbIo > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (IsUsbRndis (UsbIo)) { > + Status =3D gBS->HandleProtocol ( > + HandleBuffer[Index], > + &gEfiDevicePathProtocolGuid, > + (VOID **)&UsbRndisDataPath > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "Usb Rndis DevicePath not found\n")); > + break; > + } > + > + Status =3D IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); > + > + if (!EFI_ERROR (Status)) { > + *RndisHandle =3D HandleBuffer[Index]; > + *CdcUsbIo =3D UsbIo; > + FreePool (HandleBuffer); > + return Status; > + } > + } > + } // End of For loop > + > + FreePool (HandleBuffer); > + > + return EFI_NOT_FOUND; > +} > + > +/** > + USB Rndis Driver Binding Support. > + > + @param[in] This Protocol instance pointer. > + @param[in] ControllerHandle Handle of device to test. > + @param[in] RemainingDevicePath Optional parameter use to pick a s= pecific child > + device to start. > + > + @retval EFI_SUCCESS This driver supports this device. > + @retval EFI_ALREADY_STARTED This driver is already running on = this device. > + @retval other This driver does not support this = device. > + > +**/ > +EFI_STATUS > +EFIAPI > +UsbRndisDriverSupported ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > + ) > +{ > + EFI_STATUS Status; > + EFI_USB_IO_PROTOCOL *UsbIo; > + > + Status =3D gBS->OpenProtocol ( > + ControllerHandle, > + &gEfiUsbIoProtocolGuid, > + (VOID **)&UsbIo, > + This->DriverBindingHandle, > + ControllerHandle, > + EFI_OPEN_PROTOCOL_BY_DRIVER > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D IsSupportedDevice (UsbIo) ? EFI_SUCCESS : EFI_UNSUPPORTED; > + > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiUsbIoProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + return Status; > +} > + > +/** > + USB RNDIS Driver Binding Start. > + > + @param[in] This Protocol instance pointer. > + @param[in] ControllerHandle Handle of device to bind driver to= . > + @param[in] RemainingDevicePath Optional parameter use to pick a s= pecific child > + device to start. > + > + @retval EFI_SUCCESS This driver is added to Controller= Handle > + @retval EFI_DEVICE_ERROR This driver could not be started d= ue to a device error > + @retval EFI_OUT_OF_RESOURCES The driver could not install succe= ssfully due to a lack of resources. > + @retval other This driver does not support this = device > + > +**/ > +EFI_STATUS > +EFIAPI > +UsbRndisDriverStart ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > + ) > +{ > + EFI_STATUS Status; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath; > + EFI_USB_IO_PROTOCOL *UsbIo; > + EFI_USB_INTERFACE_DESCRIPTOR Interface; > + EFI_HANDLE RndisHandle; > + > + RndisHandle =3D ControllerHandle; > + > + Status =3D gBS->OpenProtocol ( > + ControllerHandle, > + &gEfiUsbIoProtocolGuid, > + (VOID **)&UsbIo, > + This->DriverBindingHandle, > + ControllerHandle, > + EFI_OPEN_PROTOCOL_BY_DRIVER > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D gBS->OpenProtocol ( > + ControllerHandle, > + &gEfiDevicePathProtocolGuid, > + (VOID **)&UsbEthPath, > + This->DriverBindingHandle, > + ControllerHandle, > + EFI_OPEN_PROTOCOL_BY_DRIVER > + ); > + if (EFI_ERROR (Status)) { > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiUsbIoProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + return Status; > + } > + > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiDevicePathProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + > + // Controls come here for RNDIS and CDC. If it is CDC, check whether R= NDIS is present on the same controller or not. > + if (IsUsbCdcData (UsbIo)) { > + DEBUG ((DEBUG_INFO, "Rndis CDCData interface found\n")); > + > + // Find the parent RNDIS and update the UsbIo for the CDC device > + Status =3D UpdateRndisDevice ( > + UsbEthPath, > + &UsbRndisDevice > + ); > + > + if (!EFI_ERROR (Status)) { > + DEBUG ((DEBUG_INFO, "Rndis Matching interface found\n")); > + UsbRndisDevice->UsbCdcDataHandle =3D ControllerHandle; > + UsbRndisDevice->UsbIoCdcData =3D UsbIo; > + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); > + return Status; > + } else { > + // Check if RnDis exist > + Status =3D FindMatchingRndisDev ( > + ControllerHandle, > + &UsbIo, > + &RndisHandle > + ); > + > + if (EFI_ERROR (Status)) { > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiUsbIoProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + return Status; > + } > + } > + } > + > + UsbRndisDevice =3D AllocateZeroPool (sizeof (USB_RNDIS_DEVICE)); > + > + if (!UsbRndisDevice) { > + DEBUG ((DEBUG_ERROR, "AllocateZeroPool Fail\n")); > + > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiUsbIoProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + return EFI_OUT_OF_RESOURCES; > + } > + > + Status =3D LoadAllDescriptor ( > + UsbIo, > + &UsbRndisDevice->Config > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:LoadAllDescriptor status =3D %r\n", __FUNCT= ION__, Status)); > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiUsbIoProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + FreePool (UsbRndisDevice); > + return Status; > + } > + > + Status =3D UsbIo->UsbGetInterfaceDescriptor ( > + UsbIo, > + &Interface > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status =3D %r\n",= __FUNCTION__, Status)); > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiUsbIoProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + FreePool (UsbRndisDevice->Config); > + FreePool (UsbRndisDevice); > + return Status; > + } > + > + UsbRndisDevice->Signature =3D USB_RNDIS_SIGNA= TURE; > + UsbRndisDevice->NumOfInterface =3D Interface.Inter= faceNumber; > + UsbRndisDevice->UsbRndisHandle =3D RndisHandle; > + UsbRndisDevice->UsbCdcDataHandle =3D 0; > + UsbRndisDevice->UsbIo =3D UsbIo; > + UsbRndisDevice->UsbEth.UsbEthReceive =3D RndisUndiReceiv= e; > + UsbRndisDevice->UsbEth.UsbEthTransmit =3D RndisUndiTransm= it; > + UsbRndisDevice->UsbEth.UsbEthInterrupt =3D UsbRndisInterru= pt; > + UsbRndisDevice->UsbEth.UsbEthMacAddress =3D GetUsbEthMacAdd= ress; > + UsbRndisDevice->UsbEth.UsbEthMaxBulkSize =3D UsbEthBulkSize; > + UsbRndisDevice->UsbEth.UsbHeaderFunDescriptor =3D GetUsbHeaderFun= Descriptor; > + UsbRndisDevice->UsbEth.UsbUnionFunDescriptor =3D GetUsbUnionFunD= escriptor; > + UsbRndisDevice->UsbEth.UsbEthFunDescriptor =3D GetUsbRndisFunD= escriptor; > + UsbRndisDevice->UsbEth.SetUsbEthMcastFilter =3D SetUsbRndisMcas= tFilter; > + UsbRndisDevice->UsbEth.SetUsbEthPowerPatternFilter =3D SetUsbRndisPowe= rFilter; > + UsbRndisDevice->UsbEth.GetUsbEthPowerPatternFilter =3D GetUsbRndisPowe= rFilter; > + UsbRndisDevice->UsbEth.SetUsbEthPacketFilter =3D SetUsbRndisPack= etFilter; > + UsbRndisDevice->UsbEth.GetUsbEthStatistic =3D GetRndisStatist= ic; > + > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetState =3D RndisD= ummyReturn; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStart =3D RndisU= ndiStart; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStop =3D RndisU= ndiStop; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetInitInfo =3D RndisU= ndiGetInitInfo; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetConfigInfo =3D RndisU= ndiGetConfigInfo; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInitialize =3D RndisU= ndiInitialize; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReset =3D RndisU= ndiReset; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiShutdown =3D RndisU= ndiShutdown; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInterruptEnable =3D RndisD= ummyReturn; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceiveFilter =3D RndisU= ndiReceiveFilter; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStationAddress =3D RndisD= ummyReturn; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStatistics =3D NULL; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiMcastIp2Mac =3D RndisD= ummyReturn; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiNvData =3D RndisD= ummyReturn; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetStatus =3D RndisU= ndiGetStatus; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiFillHeader =3D RndisD= ummyReturn; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiTransmit =3D NULL; > + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceive =3D NULL; > + > + UsbRndisDevice->MaxTransferSize =3D RNDIS_MAX_TRANSFER_SIZE; > + UsbRndisDevice->MaxPacketsPerTransfer =3D 1; > + UsbRndisDevice->PacketAlignmentFactor =3D 0; > + > + InitializeListHead (&UsbRndisDevice->ReceivePacketList); > + > + // This is a RNDIS interface. See whether CDC-DATA interface has alrea= dy been connected or not > + FindMatchingCdcData (UsbRndisDevice); > + > + if (UsbRndisDevice->UsbIoCdcData) { > + Status =3D gBS->InstallProtocolInterface ( > + &ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + EFI_NATIVE_INTERFACE, > + &(UsbRndisDevice->UsbEth) > + ); > + if (EFI_ERROR (Status)) { > + gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiUsbIoProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + > + FreePool (UsbRndisDevice->Config); > + FreePool (UsbRndisDevice); > + return Status; > + } > + > + GetEndpoint (UsbRndisDevice->UsbIo, UsbRndisDevice); > + > + DEBUG ((DEBUG_INFO, "Rndis DeviceHandle %r\n", UsbRndisDevice->UsbRn= disHandle)); > + DEBUG ((DEBUG_INFO, "CDC DeviceHandle %r\n", UsbRndisDevice->UsbCdcD= ataHandle)); > + return EFI_SUCCESS; > + } > + > + FreePool (UsbRndisDevice->Config); > + FreePool (UsbRndisDevice); > + > + return EFI_SUCCESS; > +} > + > +/** > + CheckandStopRndisDevice > + > + @param[in] This Protocol instance pointer. > + @param[in] ControllerHandle Handle of device to bind driver to. > + > + @retval EFI_SUCCESS This driver is added to ControllerHandle > + @retval EFI_DEVICE_ERROR This driver could not be started due to a= device error > + @retval other This driver does not support this device > + > +**/ > +EFI_STATUS > +EFIAPI > +CheckandStopRndisDevice ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle > + ) > +{ > + EFI_STATUS Status; > + EFI_USB_IO_PROTOCOL *UsbIo; > + > + Status =3D gBS->OpenProtocol ( > + ControllerHandle, > + &gEfiUsbIoProtocolGuid, > + (VOID **)&UsbIo, > + This->DriverBindingHandle, > + ControllerHandle, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (IsUsbRndis (UsbIo)) { > + Status =3D gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiUsbIoProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + DEBUG ((DEBUG_ERROR, "Rndis ControllerHandle Stop %r\n", Status)); > + return Status; > + } > + > + return EFI_UNSUPPORTED; > +} > + > +/** > + USB Rndis Driver Binding Stop. > + > + @param[in] This Protocol instance pointer. > + @param[in] ControllerHandle Handle of device to stop driver on > + @param[in] NumberOfChildren Number of Handles in ChildHandleBuff= er. If number of > + children is zero stop the entire bus= driver. > + @param[in] ChildHandleBuffer List of Child Handles to Stop. > + > + @retval EFI_SUCCESS This driver is removed ControllerHan= dle > + @retval other This driver was not removed from thi= s device > + > +**/ > +EFI_STATUS > +EFIAPI > +UsbRndisDriverStop ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN UINTN NumberOfChildren, > + IN EFI_HANDLE *ChildHandleBuffer > + ) > +{ > + EFI_STATUS Status; > + EDKII_USB_ETHERNET_PROTOCOL *UsbEthProtocol; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + > + DEBUG ((DEBUG_INFO, "UsbRndisDriverStop ControllerHandle %lx\n", Contr= ollerHandle)); > + > + Status =3D gBS->OpenProtocol ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + (VOID **)&UsbEthProtocol, > + This->DriverBindingHandle, > + ControllerHandle, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + if (EFI_ERROR (Status)) { > + Status =3D CheckandStopRndisDevice (This, ControllerHandle); > + return Status; > + } > + > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthProtocol); > + > + Status =3D gBS->CloseProtocol ( > + UsbRndisDevice->UsbCdcDataHandle, > + &gEfiUsbIoProtocolGuid, > + This->DriverBindingHandle, > + UsbRndisDevice->UsbCdcDataHandle > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:CloseProtocol status =3D %r\n", __FUNCTION_= _, Status)); > + } > + > + Status =3D gBS->UninstallProtocolInterface ( > + ControllerHandle, > + &gEdkIIUsbEthProtocolGuid, > + UsbEthProtocol > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D gBS->CloseProtocol ( > + ControllerHandle, > + &gEfiUsbIoProtocolGuid, > + This->DriverBindingHandle, > + ControllerHandle > + ); > + > + FreePool (UsbRndisDevice->Config); > + FreePool (UsbRndisDevice); > + > + DEBUG ((DEBUG_INFO, "UsbRndisDriverStop %r\n", Status)); > + return Status; > +} > + > +/** > + Entrypoint of RNDIS Driver. > + > + This function is the entrypoint of RNDIS Driver. It installs Driver Bi= nding > + Protocols together with Component Name Protocols. > + > + @param[in] ImageHandle The firmware allocated handle for the EF= I image. > + @param[in] SystemTable A pointer to the EFI System Table. > + > + @retval EFI_SUCCESS The entry point is executed successfully= . > + > +**/ > +EFI_STATUS > +EFIAPI > +UsbRndisEntry ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + gUsbRndisDriverBinding.DriverBindingHandle =3D ImageHandle; > + gUsbRndisDriverBinding.ImageHandle =3D ImageHandle; > + > + return gBS->InstallMultipleProtocolInterfaces ( > + &gUsbRndisDriverBinding.DriverBindingHandle, > + &gEfiDriverBindingProtocolGuid, > + &gUsbRndisDriverBinding, > + &gEfiComponentName2ProtocolGuid, > + &gUsbRndisComponentName2, > + NULL > + ); > +} > diff --git a/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c b/UsbNetworkPkg/Us= bRndis/UsbRndisFunction.c > new file mode 100644 > index 000000000000..e3fe737cdef1 > --- /dev/null > +++ b/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c > @@ -0,0 +1,1718 @@ > +/** @file > + This file contains code for USB Ethernet descriptor > + and specific requests implement. > + > + Copyright (c) 2023, American Megatrends International LLC. All rights = reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#include "UsbRndis.h" > + > +UINT16 gStopBulkInCnt =3D 0; > +UINT16 gBlockBulkInCnt =3D 0; > + > +/** > + Load All of device descriptor. > + > + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL= instance. > + @param[out] ConfigDesc A pointer to the configuration descr= iptor. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed becau= se the > + buffer specified by DescriptorLength and= Descriptor > + is not large enough to hold the result o= f the request. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . The transfer > + status is returned in Status. > +**/ > +EFI_STATUS > +LoadAllDescriptor ( > + IN EFI_USB_IO_PROTOCOL *UsbIo, > + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc > + ) > +{ > + EFI_STATUS Status; > + UINT32 TransStatus; > + EFI_USB_CONFIG_DESCRIPTOR Tmp; > + > + Status =3D UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:UsbGetConfigDescriptor status =3D %r\n", __= FUNCTION__, Status)); > + return Status; > + } > + > + Status =3D gBS->AllocatePool ( > + EfiBootServicesData, > + Tmp.TotalLength, > + (VOID **)ConfigDesc > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: AllocatePool status =3D %r\n", __FUNCTION_= _, Status)); > + return Status; > + } > + > + Status =3D UsbGetDescriptor ( > + UsbIo, > + USB_DESC_TYPE_CONFIG << 8 | (Tmp.ConfigurationValue - 1), = // zero based > + 0, > + Tmp.TotalLength, > + *ConfigDesc, > + &TransStatus > + ); > + return Status; > +} > + > +/** > + Returns pointer to the next descriptor for the pack of USB descriptors > + located in continues memory segment > + > + @param[in] Desc A pointer to the CONFIG_DESCRIPTOR instance. > + @param[in, out] Offset A pointer to the sum of descriptor length. > + > + @retval TRUE The request executed successfully. > + @retval FALSE No next descriptor. > + > +**/ > +BOOLEAN > +NextDescriptor ( > + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, > + IN OUT UINTN *Offset > + ) > +{ > + if ((Desc =3D=3D NULL) || (*Offset >=3D Desc->TotalLength)) { > + return FALSE; > + } > + > + if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Length =3D= =3D 0) { > + return FALSE; > + } > + > + *Offset +=3D ((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Le= ngth; > + if ( *Offset >=3D Desc->TotalLength ) { > + return FALSE; > + } > + > + return TRUE; > +} > + > +/** > + Read Function descriptor > + > + @param[in] Config A pointer to all of configuration. > + @param[in] FunDescriptorType USB CDC class descriptor SubType. > + @param[out] DataBuffer A pointer to the Data of corresponding = to device capability. > + > + @retval EFI_SUCCESS The device capability descriptor was retrie= ved > + successfully. > + @retval EFI_UNSUPPORTED No supported. > + @retval EFI_NOT_FOUND The device capability descriptor was not fo= und. > + > +**/ > +EFI_STATUS > +GetFunctionalDescriptor ( > + IN EFI_USB_CONFIG_DESCRIPTOR *Config, > + IN UINT8 FunDescriptorType, > + OUT VOID *DataBuffer > + ) > +{ > + EFI_STATUS Status; > + UINTN Offset; > + EFI_USB_INTERFACE_DESCRIPTOR *Interface; > + > + Status =3D EFI_NOT_FOUND; > + > + for (Offset =3D 0; NextDescriptor (Config, &Offset);) { > + Interface =3D (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config + Off= set); > + if (Interface->DescriptorType =3D=3D CS_INTERFACE) { > + if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->DescriptorSubtype = =3D=3D FunDescriptorType) { > + switch (FunDescriptorType) { > + case HEADER_FUN_DESCRIPTOR: > + CopyMem ( > + DataBuffer, > + (USB_HEADER_FUN_DESCRIPTOR *)Interface, > + sizeof (USB_HEADER_FUN_DESCRIPTOR) > + ); > + return EFI_SUCCESS; > + case UNION_FUN_DESCRIPTOR: > + CopyMem ( > + DataBuffer, > + (USB_UNION_FUN_DESCRIPTOR *)Interface, > + ((USB_UNION_FUN_DESCRIPTOR *)Interface)->FunctionLength > + ); > + return EFI_SUCCESS; > + case ETHERNET_FUN_DESCRIPTOR: > + CopyMem ( > + DataBuffer, > + (USB_ETHERNET_FUN_DESCRIPTOR *)Interface, > + sizeof (USB_ETHERNET_FUN_DESCRIPTOR) > + ); > + return EFI_SUCCESS; > + default: > + Status =3D EFI_UNSUPPORTED; > + break; > + } > + } > + } > + } > + > + return Status; > +} > + > +/** > + Get USB Ethernet IO endpoint and USB CDC data IO endpoint. > + > + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL i= nstance. > + @param[in, out] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE inst= ance. > + > +**/ > +VOID > +GetEndpoint ( > + IN EFI_USB_IO_PROTOCOL *UsbIo, > + IN OUT USB_RNDIS_DEVICE *UsbRndisDevice > + ) > +{ > + EFI_STATUS Status; > + UINT8 Index; > + UINT32 Result; > + EFI_USB_INTERFACE_DESCRIPTOR Interface; > + EFI_USB_ENDPOINT_DESCRIPTOR Endpoint; > + > + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status =3D %r\n",= __FUNCTION__, Status)); > + return; > + } > + > + if (Interface.NumEndpoints =3D=3D 0 ) { > + Status =3D UsbSetInterface (UsbIo, 1, 0, &Result); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:UsbSetInterface status =3D %r\n", __FUNCT= ION__, Status)); > + return; > + } > + > + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status =3D %r\n= ", __FUNCTION__, Status)); > + return; > + } > + } > + > + for (Index =3D 0; Index < Interface.NumEndpoints; Index++) { > + Status =3D UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint)= ; > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:UsbGetEndpointDescriptor status =3D %r\n"= , __FUNCTION__, Status)); > + return; > + } > + > + switch ((Endpoint.Attributes & (BIT0 | BIT1))) { > + case USB_ENDPOINT_BULK: > + if (Endpoint.EndpointAddress & BIT7) { > + UsbRndisDevice->BulkInEndpoint =3D Endpoint.EndpointAddress; > + } else { > + UsbRndisDevice->BulkOutEndpoint =3D Endpoint.EndpointAddress; > + } > + > + break; > + case USB_ENDPOINT_INTERRUPT: > + UsbRndisDevice->InterrupEndpoint =3D Endpoint.EndpointAddress; > + break; > + } > + } > +} > + > +/** > + Async USB transfer callback routine. > + > + @param[in] Data Data received or sent via the USB Asynchro= nous Transfer, if the > + transfer completed successfully. > + @param[in] DataLength The length of Data received or sent via th= e Asynchronous > + Transfer, if transfer successfully complet= es. > + @param[in] Context Data passed from UsbAsyncInterruptTransfer= () request. > + @param[in] Status Indicates the result of the asynchronous t= ransfer. > + > + @retval EFI_SUCCESS The asynchronous USB transfer request ha= s been successfully executed. > + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request fa= iled. > + > +**/ > +EFI_STATUS > +EFIAPI > +InterruptCallback ( > + IN VOID *Data, > + IN UINTN DataLength, > + IN VOID *Context, > + IN UINT32 Status > + ) > +{ > + if ((Data =3D=3D NULL) || (Context =3D=3D NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (((EFI_USB_DEVICE_REQUEST *)Data)->Request =3D=3D 0) { > + CopyMem ( > + (EFI_USB_DEVICE_REQUEST *)Context, > + (EFI_USB_DEVICE_REQUEST *)Data, > + sizeof (EFI_USB_DEVICE_REQUEST) > + ); > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + This function is used to manage a USB device with an interrupt transfe= r pipe. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROT= OCOL instance. > + @param[in] IsNewTransfer If TRUE, a new transfer will be submitte= d to USB controller. If > + FALSE, the interrupt transfer is deleted= from the device's interrupt > + transfer queue. > + @param[in] PollingInterval Indicates the periodic rate, in millisec= onds, that the transfer is to be > + executed.This parameter is required when= IsNewTransfer is TRUE. The > + value must be between 1 to 255, otherwis= e EFI_INVALID_PARAMETER is returned. > + The units are in milliseconds. > + @param[in] Request A pointer to the EFI_USB_DEVICE_REQUEST = data. > + > + @retval EFI_SUCCESS The asynchronous USB transfer request tr= ansfer has been successfully executed. > + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request fa= iled. > + > +**/ > +EFI_STATUS > +EFIAPI > +UsbRndisInterrupt ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN BOOLEAN IsNewTransfer, > + IN UINTN PollingInterval, > + IN EFI_USB_DEVICE_REQUEST *Requst > + ) > +{ > + EFI_STATUS Status; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + UINTN DataLength; > + > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); > + DataLength =3D 0; > + > + if (IsNewTransfer =3D=3D TRUE) { > + DataLength =3D sizeof (EFI_USB_DEVICE_REQUEST) + sizeof (USB_CONNECT= _SPEED_CHANGE); > + Status =3D UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( > + UsbRndisDevice->UsbIo, > + UsbRndisDevice->InterrupEndpoi= nt, > + IsNewTransfer, > + PollingInterval, > + DataLength, > + InterruptCallback, > + Requst > + ); > + > + if (Status =3D=3D EFI_INVALID_PARAMETER) { > + // Because of Stacked AsyncInterrupt request are not supported > + Status =3D UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( > + UsbRndisDevice->UsbIo, > + UsbRndisDevice->InterrupEndpoint= , > + 0, > + 0, > + 0, > + NULL, > + NULL > + ); > + } > + } else { > + Status =3D UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( > + UsbRndisDevice->UsbIo, > + UsbRndisDevice->InterrupEndpoint, > + IsNewTransfer, > + 0, > + 0, > + NULL, > + NULL > + ); > + } > + > + return Status; > +} > + > +/** > + This function is used to read USB interrupt transfer before the respon= se RNDIS message. > + > + @param[in] This A pointer to the USB_RNDIS_DEVICE instan= ce. > + > + @retval EFI_SUCCESS The USB interrupt transfer has been succ= essfully executed. > + @retval EFI_DEVICE_ERROR The USB interrupt transfer failed. > + > +**/ > +EFI_STATUS > +EFIAPI > +ReadRndisResponseInterrupt ( > + IN USB_RNDIS_DEVICE *UsbRndisDevice > + ) > +{ > + EFI_STATUS Status; > + UINT32 Data[2]; > + UINT32 UsbStatus; > + UINTN DataLength; > + > + DataLength =3D 8; > + > + ZeroMem (Data, sizeof (Data)); > + > + Status =3D UsbRndisDevice->UsbIo->UsbSyncInterruptTransfer ( > + UsbRndisDevice->UsbIo, > + UsbRndisDevice->InterrupEndpoint, > + &Data, > + &DataLength, > + 0x20, > + &UsbStatus > + ); > + > + return Status; > +} > + > +/** > + Retrieves the USB Ethernet Mac Address. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOCOL= instance. > + @param[out] MacAddress A pointer to the caller allocated USB Ethern= et Mac Address. > + > + @retval EFI_SUCCESS The USB Header Functional descriptor was= retrieved successfully. > + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. > + @retval EFI_NOT_FOUND The USB Header Functional descriptor was= not found. > + > +**/ > +EFI_STATUS > +EFIAPI > +GetUsbEthMacAddress ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT EFI_MAC_ADDRESS *MacAddress > + ) > +{ > + EFI_STATUS Status; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + USB_ETHERNET_FUN_DESCRIPTOR UsbEthDescriptor; > + CHAR16 *Data; > + CHAR16 *DataPtr; > + CHAR16 TmpStr[1]; > + UINT8 Index; > + UINT8 Hi; > + UINT8 Low; > + > + REMOTE_NDIS_QUERY_MAC_MSG RndisQueryMsg; > + REMOTE_NDIS_QUERY_MAC_CMPLT RndisQueryMsgCmplt; > + > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); > + > + ZeroMem (&RndisQueryMsg, sizeof (REMOTE_NDIS_QUERY_MAC_MSG)); > + ZeroMem (&RndisQueryMsgCmplt, sizeof (REMOTE_NDIS_QUERY_MAC_CMPLT)); > + > + RndisQueryMsg.QueryMsg.MessageType =3D RNDIS_QUERY_MSG; > + RndisQueryMsg.QueryMsg.MessageLength =3D sizeof (REMOTE_NDIS_QUERY_MAC= _MSG); > + RndisQueryMsg.QueryMsg.RequestID =3D UsbRndisDevice->RequestId; > + RndisQueryMsg.QueryMsg.Oid =3D OID_802_3_CURRENT_ADDRESS; > + > + RndisQueryMsgCmplt.QueryCmplt.MessageType =3D RNDIS_QUERY_CMPLT; > + RndisQueryMsgCmplt.QueryCmplt.MessageLength =3D sizeof (REMOTE_NDIS_QU= ERY_MAC_CMPLT); > + > + Status =3D RndisControlMsg ( > + UsbRndisDevice, > + (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsg, > + (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsgCmplt > + ); > + if (!EFI_ERROR (Status)) { > + DEBUG ((DEBUG_INFO, "Success to get Mac address from RNDIS message.\= n")); > + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { > + MacAddress->Addr[Index] =3D RndisQueryMsgCmplt.Addr[Index]; > + } > + > + UsbRndisDevice->RequestId++; > + return Status; > + } > + > + // If it is not support the OID_802_3_CURRENT_ADDRESS. > + // To check USB Ethernet functional Descriptor > + Status =3D This->UsbEthFunDescriptor (This, &UsbEthDescriptor); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:UsbEthFunDescriptor status =3D %r\n", __FUN= CTION__, Status)); > + return Status; > + } > + > + Status =3D UsbRndisDevice->UsbIo->UsbGetStringDescriptor ( > + UsbRndisDevice->UsbIo, > + 0x409, // Engl= ish-US Language ID > + UsbEthDescriptor.MacAddress, > + &Data > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:UsbGetStringDescriptor status =3D %r\n", __= FUNCTION__, Status)); > + return Status; > + } > + > + DataPtr =3D Data; > + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { > + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); > + DataPtr++; > + Hi =3D (UINT8)StrHexToUintn (TmpStr); > + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); > + DataPtr++; > + Low =3D (UINT8)StrHexToUintn (TmpStr); > + MacAddress->Addr[Index] =3D (Hi << 4) | Low; > + } > + > + return Status; > +} > + > +/** > + Retrieves the USB Ethernet Bulk transfer data size. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOCOL= instance. > + @param[out] BulkSize A pointer to the Bulk transfer data size. > + > + @retval EFI_SUCCESS The bulk transfer data size was retrieved su= ccessfully. > + @retval other Failed to retrieve the bulk transfer data si= ze. > + > +**/ > +EFI_STATUS > +EFIAPI > +UsbEthBulkSize ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT UINTN *BulkSize > + ) > +{ > + EFI_STATUS Status; > + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + > + REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG RndisQueryMsg; > + REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_CMPLT RndisQueryMsgCmplt; > + > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); > + > + ZeroMem (&RndisQueryMsg, sizeof (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG)= ); > + ZeroMem (&RndisQueryMsgCmplt, sizeof (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE= _CMPLT)); > + > + RndisQueryMsg.QueryMsg.MessageType =3D RNDIS_QUERY_MSG; > + RndisQueryMsg.QueryMsg.MessageLength =3D sizeof (REMOTE_NDIS_QUERY_MAX= _TOTAL_SIZE_MSG); > + RndisQueryMsg.QueryMsg.RequestID =3D UsbRndisDevice->RequestId; > + RndisQueryMsg.QueryMsg.Oid =3D OID_GEN_MAXIMUM_TOTAL_SIZE; > + > + RndisQueryMsgCmplt.QueryCmplt.MessageType =3D RNDIS_QUERY_CMPLT; > + RndisQueryMsgCmplt.QueryCmplt.MessageLength =3D sizeof (REMOTE_NDIS_QU= ERY_MAX_TOTAL_SIZE_CMPLT); > + > + Status =3D RndisControlMsg ( > + UsbRndisDevice, > + (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsg, > + (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsgCmplt > + ); > + if (!EFI_ERROR (Status)) { > + DEBUG ((DEBUG_INFO, "Success to get Max Total size : %X \n", RndisQ= ueryMsgCmplt.MaxTotalSize)); > + *BulkSize =3D RndisQueryMsgCmplt.MaxTotalSize; > + UsbRndisDevice->RequestId++; > + return Status; > + } > + > + Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *BulkSize =3D (UINTN)UsbEthFunDescriptor.MaxSegmentSize; > + return Status; > +} > + > +/** > + Retrieves the USB Header functional Descriptor. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET= _PROTOCOL instance. > + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated U= SB Header Functional Descriptor. > + > + @retval EFI_SUCCESS The USB Header Functional descriptor was= retrieved successfully. > + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. > + @retval EFI_NOT_FOUND The USB Header Functional descriptor was= not found. > + > +**/ > +EFI_STATUS > +EFIAPI > +GetUsbHeaderFunDescriptor ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor > + ) > +{ > + EFI_STATUS Status; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); > + > + if (UsbHeaderFunDescriptor =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status =3D GetFunctionalDescriptor ( > + UsbRndisDevice->Config, > + HEADER_FUN_DESCRIPTOR, > + UsbHeaderFunDescriptor > + ); > + return Status; > +} > + > +/** > + Retrieves the USB Union functional Descriptor. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET= _PROTOCOL instance. > + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated U= SB Union Functional Descriptor. > + > + @retval EFI_SUCCESS The USB Union Functional descriptor was= retrieved successfully. > + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. > + @retval EFI_NOT_FOUND The USB Union Functional descriptor was= not found. > + > +**/ > +EFI_STATUS > +EFIAPI > +GetUsbUnionFunDescriptor ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor > + ) > +{ > + EFI_STATUS Status; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); > + > + if (UsbUnionFunDescriptor =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status =3D GetFunctionalDescriptor ( > + UsbRndisDevice->Config, > + UNION_FUN_DESCRIPTOR, > + UsbUnionFunDescriptor > + ); > + return Status; > +} > + > +/** > + Retrieves the USB Ethernet functional Descriptor. > + > + This function get the Mac Address, Ethernet statistics, maximum segmen= t size, > + number of multicast filters, and number of pattern filters from Ethern= et > + functional Descriptor. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET= _PROTOCOL instance. > + @param[out] UsbEthFunDescriptor A pointer to the caller allocated U= SB Ethernet Functional Descriptor. > + > + @retval EFI_SUCCESS The USB Ethernet Functional descriptor = was retrieved successfully. > + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL. > + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor = was not found. > + > +**/ > +EFI_STATUS > +EFIAPI > +GetUsbRndisFunDescriptor ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor > + ) > +{ > + EFI_STATUS Status; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); > + > + if (UsbEthFunDescriptor =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status =3D GetFunctionalDescriptor ( > + UsbRndisDevice->Config, > + ETHERNET_FUN_DESCRIPTOR, > + UsbEthFunDescriptor > + ); > + return Status; > +} > + > +/** > + This request sets the Ethernet device multicast filters as specified i= n the > + sequential list of 48 bit Ethernet multicast addresses. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET= _PROTOCOL instance. > + @param[in] Value Number of filters. > + @param[in] McastAddr A pointer to the value of the multi= cast addresses. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. > + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. > + @retval EFI_UNSUPPORTED Not supported. > + > +**/ > +EFI_STATUS > +EFIAPI > +SetUsbRndisMcastFilter ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 Value, > + IN VOID *McastAddr > + ) > +{ > + EFI_STATUS Status; > + EFI_USB_DEVICE_REQUEST Request; > + UINT32 TransStatus; > + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); > + > + Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) { > + return EFI_UNSUPPORTED; > + } > + > + Request.RequestType =3D USB_ETHERNET_SET_REQ_TYPE; > + Request.Request =3D SET_ETH_MULTICAST_FILTERS_REQ; > + Request.Value =3D Value; > + Request.Index =3D UsbRndisDevice->NumOfInterface; > + Request.Length =3D Value * 6; > + > + return UsbRndisDevice->UsbIo->UsbControlTransfer ( > + UsbRndisDevice->UsbIo, > + &Request, > + EfiUsbDataOut, > + USB_ETHERNET_TRANSFER_TIMEOUT, > + McastAddr, > + Request.Length, > + &TransStatus > + ); > +} > + > +/** > + This request sets up the specified Ethernet power management pattern f= ilter as > + described in the data structure. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET_= PROTOCOL instance. > + @param[in] Value Number of filters. > + @param[in] Length Size of the power management pattern= filter data. > + @param[in] PatternFilter A pointer to the power management pa= ttern filter structure. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. > + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. > + @retval EFI_UNSUPPORTED Not supported. > + > +**/ > +EFI_STATUS > +EFIAPI > +SetUsbRndisPowerFilter ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 Value, > + IN UINT16 Length, > + IN VOID *PatternFilter > + ) > +{ > + EFI_USB_DEVICE_REQUEST Request; > + UINT32 TransStatus; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); > + > + Request.RequestType =3D USB_ETHERNET_SET_REQ_TYPE; > + Request.Request =3D SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; > + Request.Value =3D Value; > + Request.Index =3D UsbRndisDevice->NumOfInterface; > + Request.Length =3D Length; > + > + return UsbRndisDevice->UsbIo->UsbControlTransfer ( > + UsbRndisDevice->UsbIo, > + &Request, > + EfiUsbDataOut, > + USB_ETHERNET_TRANSFER_TIMEOUT, > + PatternFilter, > + Length, > + &TransStatus > + ); > +} > + > +/** > + This request retrieves the status of the specified Ethernet power mana= gement > + pattern filter from the device. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET= _PROTOCOL instance. > + @param[in] Value The filter number. > + @param[out] PatternActive A pointer to the pattern active boo= lean. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. > + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. > + @retval EFI_UNSUPPORTED Not supported. > + > +**/ > +EFI_STATUS > +EFIAPI > +GetUsbRndisPowerFilter ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 Value, > + OUT BOOLEAN *PatternActive > + ) > +{ > + EFI_USB_DEVICE_REQUEST Request; > + UINT32 TransStatus; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); > + > + Request.RequestType =3D USB_ETHERNET_GET_REQ_TYPE; > + Request.Request =3D GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; > + Request.Value =3D Value; > + Request.Index =3D UsbRndisDevice->NumOfInterface; > + Request.Length =3D USB_ETH_POWER_FILTER_LENGTH; > + > + return UsbRndisDevice->UsbIo->UsbControlTransfer ( > + UsbRndisDevice->UsbIo, > + &Request, > + EfiUsbDataIn, > + USB_ETHERNET_TRANSFER_TIMEOUT, > + PatternActive, > + USB_ETH_POWER_FILTER_LENGTH, > + &TransStatus > + ); > +} > + > +/** > + > + Converts PXE filter settings to RNDIS values > + > + @param[in] Value PXE filter data. > + @param[out] CdcFilter A pointer to the Ethernet Packet Filter Bitmap = value converted by PXE_OPFLAGS. > + > +**/ > +VOID > +ConvertFilter ( > + IN UINT16 Value, > + OUT UINT16 *CdcFilter > + ) > +{ > + UINT32 Index; > + UINT32 Count; > + static struct BIT_MAP Table[] =3D { > + { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST, NDIS_PACKET_TYPE_DI= RECTED }, > + { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST, NDIS_PACKET_TYPE_BR= OADCAST }, > + { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, NDIS_PACKET_TYPE_MU= LTICAST }, > + { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS, NDIS_PACKET_TYPE_PR= OMISCUOUS }, > + { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST, NDIS_PACKET_TYPE_AL= L_MULTICAST }, > + }; > + > + Count =3D sizeof (Table)/sizeof (Table[0]); > + > + for (Index =3D 0; (Table[Index].Src !=3D 0) && (Index < Count); Index+= +) { > + if (Table[Index].Src & Value) { > + *CdcFilter |=3D Table[Index].Dst; > + } > + } > +} > + > +/** > + > + Updates Filter settings on the device. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_STATUS > + > +**/ > +EFI_STATUS > +EFIAPI > +RndisUndiReceiveFilter ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + EFI_STATUS Status; > + UINT8 *McastList; > + UINT8 Count; > + UINT8 Index1; > + UINT8 Index2; > + UINT64 CpbAddr; > + UINT32 CpbSize; > + UINT16 SetFilter; > + PXE_CPB_RECEIVE_FILTERS *Cpb; > + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; > + > + Count =3D 0; > + CpbAddr =3D Cdb->CPBaddr; > + CpbSize =3D Cdb->CPBsize; > + SetFilter =3D (UINT16)(Cdb->OpFlags & 0x1F); > + Cpb =3D (PXE_CPB_RECEIVE_FILTERS *)(UINTN)CpbAddr; > + > + // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED) > + Nic->RxFilter =3D (UINT8)SetFilter; > + > + if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) !=3D = 0) || (Cpb !=3D NULL)) { > + if (Cpb !=3D NULL) { > + Nic->McastCount =3D (UINT8)(CpbSize / PXE_MAC_LENGTH); > + CopyMem (&Nic->McastList, Cpb, Nic->McastCount); > + } else { > + Nic->McastCount =3D 0; > + } > + > + Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth, &UsbEthFunDescriptor)= ; > + if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) { > + Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; > + DEBUG ((DEBUG_INFO, "SetUsbEthPacketFilter Nic %lx Nic->UsbEth %lx= ", Nic, Nic->UsbEth)); > + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); > + } else { > + Status =3D gBS->AllocatePool (EfiBootServicesData, Nic->McastCount= * 6, (VOID **)&McastList); > + if (EFI_ERROR (Status)) { > + return PXE_STATCODE_INVALID_PARAMETER; > + } > + > + if (Cpb !=3D NULL) { > + for (Index1 =3D 0; Index1 < Nic->McastCount; Index1++) { > + for (Index2 =3D 0; Index2 < 6; Index2++) { > + McastList[Count++] =3D Cpb->MCastList[Index1][Index2]; > + } > + } > + } > + > + Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; > + if (Cpb !=3D NULL) { > + Nic->UsbEth->SetUsbEthMcastFilter (Nic->UsbEth, Nic->McastCount,= McastList); > + } > + > + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); > + FreePool (McastList); > + } > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + This request is used to configure device Ethernet packet filter settin= gs. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROT= OCOL instance. > + @param[in] Value Packet Filter Bitmap. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > + > +**/ > +EFI_STATUS > +EFIAPI > +SetUsbRndisPacketFilter ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 Value > + ) > +{ > + return EFI_SUCCESS; > +} > + > +/** > + This request is used to retrieve a statistic based on the feature sele= ctor. > + > + @param[in] This A pointer to the EDKII_USB_ETHERNET_= PROTOCOL instance. > + @param[in] FeatureSelector Value of the feature selector. > + @param[out] Statistic A pointer to the 32 bit unsigned int= eger. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_TIMEOUT A timeout occurred executing the request= . > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid val= ue. > + @retval EFI_UNSUPPORTED Not supported. > + > +**/ > +EFI_STATUS > +EFIAPI > +GetRndisStatistic ( > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN UINT16 FeatureSelector, > + OUT VOID *Statistic > + ) > +{ > + return EFI_SUCCESS; > +} > + > +/** > + This function is called when UndiStart is invoked. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + > +**/ > +EFI_STATUS > +EFIAPI > +RndisUndiStart ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + EFI_STATUS Status; > + > + DEBUG ((DEBUG_INFO, "RndisUndiStart Nic %lx Cdb %lx Nic State %x\n", N= ic, Cdb, Nic->State)); > + > + // Issue Rndis Reset and bring the device to RNDIS_BUS_INITIALIZED sta= te > + Status =3D RndisUndiReset (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + RndisUndiReset (Cdb, Nic); > + } > + > + Status =3D RndisUndiInitialize (Cdb, Nic); > + if (EFI_ERROR (Status)) { > + RndisUndiInitialize (Cdb, Nic); > + } > + > + RndisUndiShutdown (Cdb, Nic); > + > + return EFI_SUCCESS; > +} > + > +/** > + This function is called when Undistop is invoked. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > +**/ > +EFI_STATUS > +EFIAPI > +RndisUndiStop ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + DEBUG ((DEBUG_INFO, "RndisUndiStop State %x\n", Nic->State)); > + return EFI_SUCCESS; > +} > + > +/** > + This function is called when UndiGetInitInfo is invoked. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + > +**/ > +EFI_STATUS > +EFIAPI > +RndisUndiGetInitInfo ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDevice; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + PXE_DB_GET_INIT_INFO *Db; > + > + DEBUG ((DEBUG_INFO, "RndisUndiGetInitInfo\n")); > + > + UsbEthDevice =3D Nic->UsbEth; > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthDevice); > + > + Db =3D (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr; > + > + Db->FrameDataLen =3D UsbRndisDevice->MaxTransferSize - sizeof (REMOTE_= NDIS_PACKET_MSG) - PXE_MAC_HEADER_LEN_ETHER; > + // Limit Max MTU size to 1500 bytes as RNDIS spec. > + if (Db->FrameDataLen > PXE_MAX_TXRX_UNIT_ETHER) { > + Db->FrameDataLen =3D PXE_MAX_TXRX_UNIT_ETHER; > + } > + > + DEBUG ((DEBUG_INFO, "Db->FrameDataLen %x\n", Db->FrameDataLen)); > + > + return EFI_SUCCESS; > +} > + > +/** > + This function is called when RndisUndiGetConfigInfo is invoked. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + > +**/ > +EFI_STATUS > +EFIAPI > +RndisUndiGetConfigInfo ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + DEBUG ((DEBUG_INFO, "RndisUndiGetConfigInfo\n")); > + return EFI_SUCCESS; > +} > + > +/** > + This function is called when UndiInitialize is invoked. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_UNSUPPORTED Not supported. > + > +**/ > +EFI_STATUS > +EFIAPI > +RndisUndiInitialize ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDriver; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + REMOTE_NDIS_INITIALIZE_MSG RndisInitMsg; > + REMOTE_NDIS_INITIALIZE_CMPLT RndisInitMsgCmplt; > + EFI_STATUS Status; > + > + DEBUG ((DEBUG_INFO, "RndisUndiInitialize\n")); > + > + UsbEthDriver =3D Nic->UsbEth; > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver); > + > + ZeroMem (&RndisInitMsg, sizeof (REMOTE_NDIS_INITIALIZE_MSG)); > + ZeroMem (&RndisInitMsgCmplt, sizeof (REMOTE_NDIS_INITIALIZE_CMPLT)); > + > + RndisInitMsg.MessageType =3D RNDIS_INITIALIZE_MSG; > + RndisInitMsg.MessageLength =3D sizeof (REMOTE_NDIS_INITIALIZE_MSG); > + RndisInitMsg.RequestID =3D UsbRndisDevice->RequestId; > + RndisInitMsg.MajorVersion =3D RNDIS_MAJOR_VERSION; > + RndisInitMsg.MinorVersion =3D RNDIS_MINOR_VERSION; > + RndisInitMsg.MaxTransferSize =3D RNDIS_MAX_TRANSFER_SIZE; > + > + RndisInitMsgCmplt.MessageType =3D RNDIS_INITIALIZE_CMPLT; > + RndisInitMsgCmplt.MessageLength =3D sizeof (REMOTE_NDIS_INITIALIZE_CMP= LT); > + > + Status =3D RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER *)= &RndisInitMsg, (REMOTE_NDIS_MSG_HEADER *)&RndisInitMsgCmplt); > + > + UsbRndisDevice->RequestId++; > + > + if (EFI_ERROR (Status) || (RndisInitMsgCmplt.Status & 0x80000000)) { > + return Status; > + } > + > + // Only Wired Medium is supported > + if (RndisInitMsgCmplt.Medium) { > + return EFI_UNSUPPORTED; > + } > + > + UsbRndisDevice->Medium =3D RndisInitMsgCmplt.Medium; > + UsbRndisDevice->MaxPacketsPerTransfer =3D RndisInitMsgCmplt.MaxPackets= PerTransfer; > + UsbRndisDevice->MaxTransferSize =3D RndisInitMsgCmplt.MaxTransfe= rSize; > + UsbRndisDevice->PacketAlignmentFactor =3D RndisInitMsgCmplt.PacketAlig= nmentFactor; > + > + DEBUG ((DEBUG_INFO, "Medium : %x \n", RndisInitMsgCmplt.Medium)); > + DEBUG ((DEBUG_INFO, "MaxPacketsPerTransfer : %x \n", RndisInitMsgCmplt= .MaxPacketsPerTransfer)); > + DEBUG ((DEBUG_INFO, "MaxTransferSize : %x\n", RndisInitMsgCmplt.MaxTra= nsferSize)); > + DEBUG ((DEBUG_INFO, "PacketAlignmentFactor : %x\n", RndisInitMsgCmplt.= PacketAlignmentFactor)); > + > + return Status; > +} > + > +/** > + This function is called when UndiReset is invoked. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_DEVICE_ERROR The request failed due to a device error= . > + > +**/ > +EFI_STATUS > +EFIAPI > +RndisUndiReset ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDriver; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + REMOTE_NDIS_RESET_MSG RndisResetMsg; > + REMOTE_NDIS_RESET_CMPLT RndisResetCmplt; > + EFI_STATUS Status; > + > + DEBUG ((DEBUG_INFO, "RndisUndiReset\n")); > + > + UsbEthDriver =3D Nic->UsbEth; > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver); > + > + ZeroMem (&RndisResetMsg, sizeof (REMOTE_NDIS_RESET_MSG)); > + ZeroMem (&RndisResetCmplt, sizeof (REMOTE_NDIS_RESET_CMPLT)); > + > + RndisResetMsg.MessageType =3D RNDIS_RESET_MSG; > + RndisResetMsg.MessageLength =3D sizeof (REMOTE_NDIS_RESET_MSG); > + > + RndisResetCmplt.MessageType =3D RNDIS_RESET_CMPLT; > + RndisResetCmplt.MessageLength =3D sizeof (REMOTE_NDIS_RESET_CMPLT); > + > + Status =3D RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER *)= &RndisResetMsg, (REMOTE_NDIS_MSG_HEADER *)&RndisResetCmplt); > + > + UsbRndisDevice->RequestId =3D 1; // Let's start with 1 > + > + if (EFI_ERROR (Status) || (RndisResetCmplt.Status & 0x80000000)) { > + return EFI_DEVICE_ERROR; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + This function is called when UndiShutdown is invoked. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + > +**/ > +EFI_STATUS > +EFIAPI > +RndisUndiShutdown ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDriver; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + REMOTE_NDIS_HALT_MSG RndisHltMsg; > + EFI_STATUS Status; > + > + DEBUG ((DEBUG_INFO, "RndisUndiShutdown\n")); > + > + UsbEthDriver =3D Nic->UsbEth; > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver); > + > + ZeroMem (&RndisHltMsg, sizeof (REMOTE_NDIS_HALT_MSG)); > + > + RndisHltMsg.MessageType =3D RNDIS_HLT_MSG; > + RndisHltMsg.MessageLength =3D sizeof (REMOTE_NDIS_HALT_MSG); > + > + Status =3D RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER *)= &RndisHltMsg, NULL); > + > + if (Status =3D=3D EFI_DEVICE_ERROR) { > + Status =3D EFI_SUCCESS; > + } > + > + UsbRndisDevice->RequestId =3D 1; > + return Status; > +} > + > +/** > + Update the Media connection. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + > +**/ > +EFI_STATUS > +EFIAPI > +RndisUndiGetStatus ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + Cdb->StatFlags &=3D ~(PXE_STATFLAGS_GET_STATUS_NO_MEDIA); > + return EFI_SUCCESS; > +} > + > +/** > + Transmit the data after appending RNDIS header. > + > + @param[in] Cdb A pointer to the command descriptor bloc= k. > + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROT= OCOL instance. > + @param[in] BulkOutData A pointer to the buffer of data that wil= l be transmitted to USB > + device or received from USB device. > + @param[in, out] DataLength A pointer to the PacketLength. > + > + @retval EFI_SUCCESS The request executed successfully. > + > +**/ > +EFI_STATUS > +EFIAPI > +RndisUndiTransmit ( > + IN PXE_CDB *Cdb, > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN VOID *BulkOutData, > + IN OUT UINTN *DataLength > + ) > +{ > + EFI_STATUS Status; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + REMOTE_NDIS_PACKET_MSG *RndisPacketMsg; > + UINTN TransferLength; > + > + DEBUG ((DEBUG_INFO, "RndisUndiTransmit DataLength : %x\n", *DataLength= )); > + > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); > + > + RndisPacketMsg =3D AllocateZeroPool (sizeof (REMOTE_NDIS_PACKET_MSG) += *DataLength); > + if (RndisPacketMsg =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + RndisPacketMsg->MessageType =3D RNDIS_PACKET_MSG; > + RndisPacketMsg->MessageLength =3D sizeof (REMOTE_NDIS_PACKET_MSG) + (U= INT32)*DataLength; > + RndisPacketMsg->DataOffset =3D sizeof (REMOTE_NDIS_PACKET_MSG) - 8; > + RndisPacketMsg->DataLength =3D (UINT32)*DataLength; > + > + CopyMem ( > + ((UINT8 *)RndisPacketMsg) + sizeof (REMOTE_NDIS_PACKET_MSG), > + BulkOutData, > + *DataLength > + ); > + > + TransferLength =3D RndisPacketMsg->MessageLength; > + > + Status =3D RndisTransmitDataMsg ( > + UsbRndisDevice, > + (REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg, > + &TransferLength > + ); > + > + DEBUG ((DEBUG_INFO, "\nRndisUndiTransmit TransferLength %lx\n", Transf= erLength)); > + > + FreePool (RndisPacketMsg); > + > + return Status; > +} > + > +/** > + Receives and removes RNDIS header and returns the raw data. > + > + @param[in] Cdb A pointer to the command descriptor bloc= k. > + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROT= OCOL instance. > + @param[in, out] BulkInData A pointer to the buffer of data that wil= l be transmitted to USB > + device or received from USB device. > + @param[in, out] DataLength A pointer to the PacketLength. > + > + @retval EFI_SUCCESS The request executed successfully. > + @retval EFI_BUFFER_TOO_SMALL The user provided buffer is too small > + @retval EFI_NOT_FOUND No buffer was found in the list. > + > +**/ > +EFI_STATUS > +EFIAPI > +RndisUndiReceive ( > + IN PXE_CDB *Cdb, > + IN EDKII_USB_ETHERNET_PROTOCOL *This, > + IN OUT VOID *BulkInData, > + IN OUT UINTN *DataLength > + ) > +{ > + EFI_STATUS Status; > + USB_RNDIS_DEVICE *UsbRndisDevice; > + REMOTE_NDIS_PACKET_MSG *RndisPacketMsg; > + UINTN TransferLength; > + VOID *Buffer; > + PACKET_LIST *HeadPacket; > + PACKET_LIST *PacketList; > + > + // Check if there is any outstanding packet to receive > + // The buffer allocated has a linked List followed by the packet. > + > + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); > + Buffer =3D NULL; > + HeadPacket =3D NULL; > + > + while (1) { > + Buffer =3D AllocateZeroPool (sizeof (PACKET_LIST) + sizeof (REMOTE_N= DIS_PACKET_MSG) + UsbRndisDevice->MaxTransferSize); > + if (Buffer =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + RndisPacketMsg =3D (REMOTE_NDIS_PACKET_MSG *)(sizeof = (PACKET_LIST) + (UINT8 *)Buffer); > + PacketList =3D (PACKET_LIST *)Buffer; > + PacketList->PacketStartBuffer =3D (UINT8 *)Buffer + sizeof (PACKET_L= IST); > + // Save the original address for freeing it up > + PacketList->OrgBuffer =3D (UINT8 *)Buffer; > + TransferLength =3D UsbRndisDevice->MaxTransferSize; > + > + Status =3D RndisReceiveDataMsg ( > + UsbRndisDevice, > + (REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg, > + &TransferLength > + ); > + > + if (EFI_ERROR (Status) || (TransferLength =3D=3D 0)) { > + FreePool (Buffer); > + break; > + } > + > + // Collect all the RNDIS packet in Linked list. > + if ((RndisPacketMsg->MessageType =3D=3D RNDIS_PACKET_MSG) && > + (RndisPacketMsg->DataOffset =3D=3D sizeof (REMOTE_NDIS_PACKET_MS= G) - RNDIS_RESERVED_BYTE_LENGTH) && > + (TransferLength >=3D RndisPacketMsg->MessageLength)) > + { > + // Insert Packet > + PacketList->RemainingLength =3D TransferLength; > + InsertTailList (&UsbRndisDevice->ReceivePacketList, Buffer); > + } else { > + FreePool (Buffer); > + } > + } > + > + while (!IsListEmpty (&UsbRndisDevice->ReceivePacketList)) { > + HeadPacket =3D (PACKET_LIST *)GetFirstNode (&UsbRndisDevice->Receive= PacketList); > + > + RndisPacketMsg =3D (REMOTE_NDIS_PACKET_MSG *)(UINT8 *)HeadPacket->Pa= cketStartBuffer; > + > + PrintRndisMsg ((REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg); > + > + // Check whether the packet is valid RNDIS packet. > + if ((HeadPacket->RemainingLength > sizeof (REMOTE_NDIS_PACKET_MSG)) = && (RndisPacketMsg->MessageType =3D=3D RNDIS_PACKET_MSG) && > + (RndisPacketMsg->DataOffset =3D=3D (sizeof (REMOTE_NDIS_PACKET_M= SG) - RNDIS_RESERVED_BYTE_LENGTH)) && > + (HeadPacket->RemainingLength >=3D RndisPacketMsg->MessageLength)= ) > + { > + if (*DataLength >=3D RndisPacketMsg->DataLength) { > + CopyMem ( > + BulkInData, > + (UINT8 *)RndisPacketMsg + (RndisPacketMsg->DataOffset + RNDIS_= RESERVED_BYTE_LENGTH), > + RndisPacketMsg->DataLength > + ); > + > + *DataLength =3D RndisPacketMsg->DataLength; > + > + HeadPacket->RemainingLength =3D HeadPacket->RemainingLength - = RndisPacketMsg->MessageLength; > + HeadPacket->PacketStartBuffer =3D (UINT8 *)RndisPacketMsg + Rndi= sPacketMsg->MessageLength; > + > + return EFI_SUCCESS; > + } else { > + *DataLength =3D RndisPacketMsg->DataLength; > + return EFI_BUFFER_TOO_SMALL; > + } > + } > + > + RemoveEntryList (&HeadPacket->PacketList); > + FreePool ((PACKET_LIST *)HeadPacket->OrgBuffer); > + } > + > + return EFI_NOT_FOUND; > +} > + > +/** > + This is a dummy function which just returns. Unimplemented EDKII_USB_E= THERNET_PROTOCOL functions > + point to this function. > + > + @param[in] Cdb A pointer to the command descriptor block. > + @param[in] Nic A pointer to the Network interface controller data. > + > + @retval EFI_SUCCESS The request executed successfully. > + > +**/ > +EFI_STATUS > +EFIAPI > +RndisDummyReturn ( > + IN PXE_CDB *Cdb, > + IN NIC_DATA *Nic > + ) > +{ > + DEBUG ((DEBUG_INFO, "RndisDummyReturn called\n")); > + return EFI_SUCCESS; > +} > + > +/** > + This function send the RNDIS command through the device's control endp= oint > + > + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE instan= ce. > + @param[in] RndisMsg A pointer to the REMOTE_NDIS_MSG_HEADER = data. > + @param[out] RndisMsgResponse A pointer to the REMOTE_NDIS_MSG_HEADER = data for getting responses. > + > + @retval EFI_SUCCESS The bulk transfer has been successfully = executed. > + > +**/ > +EFI_STATUS > +RndisControlMsg ( > + IN USB_RNDIS_DEVICE *UsbRndisDevice, > + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, > + OUT REMOTE_NDIS_MSG_HEADER *RndisMsgResponse > + ) > +{ > + EFI_USB_IO_PROTOCOL *UsbIo =3D UsbRndisDevice->UsbIo; > + EFI_USB_DEVICE_REQUEST DevReq; > + UINT32 UsbStatus; > + EFI_STATUS Status; > + UINT32 SaveResponseType; > + UINT32 SaveResponseLength; > + UINT32 Index; > + REMOTE_NDIS_INITIALIZE_CMPLT *RndisInitCmplt; > + > + SaveResponseType =3D 0; > + SaveResponseLength =3D 0; > + RndisInitCmplt =3D (REMOTE_NDIS_INITIALIZE_CMPLT *)RndisMsgRespons= e; > + > + if (RndisMsgResponse) { > + SaveResponseType =3D RndisMsgResponse->MessageType; > + SaveResponseLength =3D RndisMsgResponse->MessageLength; > + } > + > + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); > + > + DevReq.RequestType =3D USB_REQ_TYPE_CLASS | USB_TARGET_INTERFACE; > + DevReq.Request =3D SEND_ENCAPSULATED_COMMAND; > + DevReq.Value =3D 0; > + DevReq.Index =3D 0; > + DevReq.Length =3D (UINT16)RndisMsg->MessageLength; > + > + PrintRndisMsg (RndisMsg); > + > + Status =3D UsbIo->UsbControlTransfer ( > + UsbIo, > + &DevReq, > + EfiUsbDataOut, > + USB_ETHERNET_TRANSFER_TIMEOUT, > + RndisMsg, > + RndisMsg->MessageLength, > + &UsbStatus > + ); > + > + DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x Status : %r Rndis= MsgResponse : %lx\n", UsbStatus, Status, RndisMsgResponse)); > + > + // Error or no response expected > + if ((EFI_ERROR (Status)) || (RndisMsgResponse =3D=3D NULL)) { > + DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x Status : %r\n",= UsbStatus, Status)); > + return Status; > + } > + > + for (Index =3D 0; Index < (RNDIS_CONTROL_TIMEOUT/100); Index++) { > + ReadRndisResponseInterrupt (UsbRndisDevice); > + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); > + > + DevReq.RequestType =3D USB_ENDPOINT_DIR_IN | USB_REQ_TYPE_CLASS | US= B_TARGET_INTERFACE; > + DevReq.Request =3D GET_ENCAPSULATED_RESPONSE; > + DevReq.Value =3D 0; > + DevReq.Index =3D 0; > + DevReq.Length =3D (UINT16)RndisMsgResponse->MessageLength; > + > + Status =3D UsbIo->UsbControlTransfer ( > + UsbIo, > + &DevReq, > + EfiUsbDataIn, > + USB_ETHERNET_TRANSFER_TIMEOUT, > + RndisMsgResponse, > + RndisMsgResponse->MessageLength, > + &UsbStatus > + ); > + > + DEBUG ((DEBUG_INFO, "RndisControlMsg Response: UsbStatus : %x Status= : %r \n", UsbStatus, Status)); > + > + PrintRndisMsg (RndisMsgResponse); > + > + if (!EFI_ERROR (Status)) { > + if ((RndisInitCmplt->RequestID !=3D ((REMOTE_NDIS_INITIALIZE_CMPLT= *)RndisMsg)->RequestID) || (RndisInitCmplt->MessageType !=3D SaveResponseT= ype)) { > + DEBUG ((DEBUG_INFO, "Retry the response\n")); > + > + RndisMsgResponse->MessageType =3D SaveResponseType; > + RndisMsgResponse->MessageLength =3D SaveResponseLength; > + continue; > + } > + } > + > + return Status; > + } > + > + DEBUG ((DEBUG_INFO, "RndisControlMsg: TimeOut\n")); > + > + return EFI_TIMEOUT; > +} > + > +/** > + This function send the RNDIS command through the device's Data endpoin= t > + > + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE inst= ance. > + @param[in] RndisMsg A pointer to the REMOTE_NDIS_MSG_HEADE= R to send out. > + @param[in, out] TransferLength The length of the RndisMsg data to tra= nsfer. > + > + @retval EFI_SUCCESS The request executed successfully. > + > +**/ > +EFI_STATUS > +RndisTransmitDataMsg ( > + IN USB_RNDIS_DEVICE *UsbRndisDevice, > + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, > + IN OUT UINTN *TransferLength > + ) > +{ > + EFI_STATUS Status; > + UINT32 UsbStatus; > + > + if (UsbRndisDevice->BulkInEndpoint =3D=3D 0) { > + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); > + } > + > + PrintRndisMsg (RndisMsg); > + > + Status =3D UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer ( > + UsbRndisDevice->UsbIoCdcData, > + UsbRndisDevice->BulkOutEndpoi= nt, > + RndisMsg, > + TransferLength, > + USB_TX_ETHERNET_BULK_TIMEOUT, > + &UsbStatus > + ); > + > + if (Status =3D=3D EFI_SUCCESS) { > + gStopBulkInCnt =3D MAXIMUM_STOPBULKIN_CNT; // After sending cmd = ,we will polling receive package for MAXIMUM_STOPBULKIN_CNT times > + } > + > + return Status; > +} > + > +/** > + This function send the RNDIS command through the device's Data endpoin= t > + > + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE in= stance. > + @param[in, out] RndisMsg A pointer to the REMOTE_NDIS_MSG_HEA= DER to send out. > + @param[in, out] TransferLength The length of the RndisMsg data to t= ransfer. > + > + @retval EFI_SUCCESS The request executed successfully. > + > +**/ > +EFI_STATUS > +RndisReceiveDataMsg ( > + IN USB_RNDIS_DEVICE *UsbRndisDevice, > + IN OUT REMOTE_NDIS_MSG_HEADER *RndisMsg, > + IN OUT UINTN *TransferLength > + ) > +{ > + EFI_STATUS Status; > + UINT32 UsbStatus; > + > + UsbStatus =3D 0; > + > + if (UsbRndisDevice->BulkInEndpoint =3D=3D 0) { > + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); > + } > + > + // Use gStopBulkInCnt to stop BulkIn command > + if (gStopBulkInCnt || LAN_BULKIN_CMD_CONTROL) { > + Status =3D UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer ( > + UsbRndisDevice->UsbIoCdcDat= a, > + UsbRndisDevice->BulkInEndpo= int, > + RndisMsg, > + TransferLength, > + USB_RX_ETHERNET_BULK_TIMEOU= T, > + &UsbStatus > + ); > + > + if (!EFI_ERROR (Status)) { > + gStopBulkInCnt =3D MINIMUM_STOPBULKIN_CNT; > + } else { > + gStopBulkInCnt--; > + } > + } else { > + Status =3D EFI_TIMEOUT; > + *TransferLength =3D 0; > + gBlockBulkInCnt++; > + } > + > + if (gBlockBulkInCnt > BULKIN_CMD_POLLING_CNT) { > + gStopBulkInCnt =3D MINIMUM_STOPBULKIN_CNT; > + gBlockBulkInCnt =3D 0; > + } > + > + PrintRndisMsg (RndisMsg); > + > + return Status; > +} > + > +/** > + Prints RNDIS Header and Data > + > + @param[in] RndisMsg A pointer to the REMOTE_NDIS_MSG_HEADER data. > + > +**/ > +VOID > +PrintRndisMsg ( > + IN REMOTE_NDIS_MSG_HEADER *RndisMsg > + ) > +{ > + UINTN Length; > + REMOTE_NDIS_QUERY_CMPLT *RndisQueryCmplt; > + > + Length =3D 0; > + > + switch (RndisMsg->MessageType) { > + case RNDIS_PACKET_MSG: > + DEBUG ((DEBUG_INFO, "RNDIS_PACKET_MSG:\n")); > + Length =3D sizeof (REMOTE_NDIS_PACKET_MSG) + 0x14; > + break; > + case RNDIS_INITIALIZE_MSG: > + DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_MSG:\n")); > + Length =3D sizeof (REMOTE_NDIS_INITIALIZE_MSG); > + break; > + case RNDIS_INITIALIZE_CMPLT: > + DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_CMPLT:\n")); > + Length =3D sizeof (REMOTE_NDIS_INITIALIZE_CMPLT); > + break; > + case RNDIS_HLT_MSG: > + DEBUG ((DEBUG_INFO, "RNDIS_HLT_MSG:\n")); > + Length =3D sizeof (REMOTE_NDIS_HALT_MSG); > + break; > + case RNDIS_QUERY_MSG: > + DEBUG ((DEBUG_INFO, "RNDIS_QUERY_MSG:\n")); > + Length =3D sizeof (REMOTE_NDIS_QUERY_MSG); > + break; > + case RNDIS_QUERY_CMPLT: > + DEBUG ((DEBUG_INFO, "RNDIS_QUERY_CMPLT:\n")); > + RndisQueryCmplt =3D (REMOTE_NDIS_QUERY_CMPLT *)RndisMsg; > + Length =3D sizeof (REMOTE_NDIS_QUERY_CMPLT) + RndisQueryC= mplt->InformationBufferLength; > + break; > + case RNDIS_SET_MSG: > + DEBUG ((DEBUG_INFO, "RNDIS_SET_MSG:\n")); > + Length =3D sizeof (REMOTE_NDIS_SET_MSG); > + break; > + case RNDIS_SET_CMPLT: > + DEBUG ((DEBUG_INFO, "RNDIS_SET_CMPLT:\n")); > + Length =3D sizeof (REMOTE_NDIS_SET_CMPLT); > + break; > + case RNDIS_RESET_MSG: > + DEBUG ((DEBUG_INFO, "RNDIS_RESET_MSG:\n")); > + Length =3D sizeof (REMOTE_NDIS_RESET_MSG); > + break; > + case RNDIS_RESET_CMPLT: > + DEBUG ((DEBUG_INFO, "RNDIS_RESET_CMPLT:\n")); > + Length =3D sizeof (REMOTE_NDIS_RESET_CMPLT); > + break; > + case RNDIS_INDICATE_STATUS_MSG: > + DEBUG ((DEBUG_INFO, "RNDIS_INDICATE_STATUS_MSG:\n")); > + Length =3D sizeof (REMOTE_NDIS_INDICATE_STATUS_MSG); > + break; > + case RNDIS_KEEPALIVE_MSG: > + DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_MSG:\n")); > + Length =3D sizeof (REMOTE_NDIS_KEEPALIVE_MSG); > + break; > + case RNDIS_KEEPALIVE_CMPLT: > + DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_CMPLT:\n")); > + Length =3D sizeof (REMOTE_NDIS_KEEPALIVE_CMPLT); > + } > + > + if (Length) { > + UINTN Index =3D 0; > + for ( ; Length; Length -=3D 4, Index++) { > + DEBUG ((DEBUG_INFO, "%8X\t", *((UINT32 *)RndisMsg + Index))); > + if (((Index % 4) =3D=3D 3) && (Index !=3D 0)) { > + DEBUG ((DEBUG_INFO, "\n")); > + } > + > + if ((Length < 8) && (Length > 4)) { > + UINT32 Data32; > + Index++; > + Data32 =3D *((UINT32 *)RndisMsg + Index); > + DEBUG ((DEBUG_INFO, "%8X\t", Data32)); > + break; > + } > + } > + > + if (Index % 4) { > + DEBUG ((DEBUG_INFO, "\n")); > + } > + } > +} > diff --git a/UsbNetworkPkg/ReadMe.md b/UsbNetworkPkg/ReadMe.md > new file mode 100644 > index 000000000000..cb70684f0bf1 > --- /dev/null > +++ b/UsbNetworkPkg/ReadMe.md > @@ -0,0 +1,65 @@ > +# UsbNetworkPkg > + > +This document is intend to provide package information, include the inte= rface details. > + > +# INDEX > + * [Introduction](#introduction) > + * [Components](#components) > + * [[NetworkCommon]](#networkcommon) > + * [[UsbCdcEcm]](#usbcdcecm) > + * [[UsbCdcNcm]](#usbcdcncm) > + * [[UsbRndis]](#usbrndis) > + > +# Introduction > +UsbNetworkPkg provides network functions for USB LAN devices. > + > +# Components > +Below module is included in this package:
> +- NetworkCommon > +- UsbCdcEcm > +- UsbCdcNcm > +- UsbRndis > + > +## [NetworkCommon] > +Provides a LAN driver based on UEFI specification(UNDI). It supports USB= communication class subclass devices and USB Rndis devices, depending on t= he UsbEthernetProtocol. > + > +## Required Components > +- NetworkPkg > + > +## [UsbCdcEcm] > +This driver provides a communication interface for USB Ethernet devices = that follows the ECM protocol. The driver installs UsbEthernetProtocol with= ECM functions which are consumed by the NetworkCommon driver. > + > +The driver is compatible with the following USB class codes: > +|Class Code|SubClass Code|Protocol Code| > +|:--------:|:-----------:|:-----------:| > +|0x02|0x06|0x00| > + > +## Required Components > +- NetworkCommon > +- MdeModulePkg(USB bus driver) > + > +## [UsbCdcNcm] > +This driver provides a communication interface for USB Ethernet devices = that follows the NCM protocol. The driver installs UsbEthernetProtocol with= NCM functions which are consumed by the NetworkCommon driver. > + > +The driver is compatible with the following USB class codes: > +|Class Code|SubClass Code|Protocol Code| > +|:--------:|:-----------:|:-----------:| > +|0x02|0x0D|0x00| > + > +## Required Components > +- NetworkCommon > +- MdeModulePkg(USB bus driver) > + > +## [UsbRndis] > +This driver provides a communication interface for USB Ethernet devices = that follows the RNDIS protocol. The driver installs UsbEthernetProtocol wi= th RNDIS functions which are consumed by the NetworkCommon driver. > + > +The driver is compatible with the following USB class codes: > +|Class Code|SubClass Code|Protocol Code| > +|:--------:|:-----------:|:-----------:| > +|0x02|0x02|0xFF| > +|0xEF|0x04|0x01| > + > +## Required Components > +- NetworkCommon > +- MdeModulePkg(USB bus driver) > + > diff --git a/UsbNetworkPkg/ReleaseNotes.md b/UsbNetworkPkg/ReleaseNotes.m= d > new file mode 100644 > index 000000000000..f8ccccdb0830 > --- /dev/null > +++ b/UsbNetworkPkg/ReleaseNotes.md > @@ -0,0 +1,11 @@ > +# UsbNetworkPkg Release Notes > + > +# Release History > +- [1.00](#100) > + > +## 1.00 > + > +**Release Date:** Mar 10, 2022 > + > +**New Features** > +- UsbNetworkPkg first release. > -- > 2.35.1.windows.2 > -The information contained in this message may be confidential and propri= etary to American Megatrends (AMI). This communication is intended to be re= ad only by the individual or entity to whom it is addressed or by their des= ignee. If the reader of this message is not the intended recipient, you are= on notice that any distribution of this message, in any form, is strictly = prohibited. Please promptly notify the sender by reply e-mail or by telepho= ne at 770-246-8600, and then delete or destroy all copies of the transmissi= on.