diff --git a/UefiPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf b/UefiPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf new file mode 100644 index 0000000000..981a652a70 --- /dev/null +++ b/UefiPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf @@ -0,0 +1,54 @@ +## @file +# Set TPM device type +# +# In SecurityPkg, this module initializes the TPM device type based on a UEFI +# variable and/or hardware detection. In OvmfPkg, the module only performs TPM2 +# hardware detection. +# +# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+# Copyright (C) 2018, Red Hat, Inc. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2ConfigPei + FILE_GUID = BF7F2B0C-9F2F-4889-AB5C-12460022BE87 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = Tcg2ConfigPeimEntryPoint + +[Sources] + Tcg2ConfigPeim.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + PeimEntryPoint + DebugLib + PeiServicesLib + Tpm12CommandLib + Tpm12DeviceLib + Tpm2DeviceLib + +[Guids] + gEfiTpmDeviceSelectedGuid ## PRODUCES ## GUID # Used as a PPI GUID + gEfiTpmDeviceInstanceTpm20DtpmGuid ## SOMETIMES_CONSUMES + gEfiTpmDeviceInstanceTpm12Guid ## SOMETIMES_CONSUMES + +[Ppis] + gPeiTpmInitializationDonePpiGuid ## SOMETIMES_PRODUCES + +[Pcd] + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## PRODUCES + +[Depex.IA32, Depex.X64] + TRUE + +[Depex.ARM, Depex.AARCH64] + gOvmfTpmDiscoveredPpiGuid diff --git a/UefiPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c b/UefiPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c new file mode 100644 index 0000000000..b919f8cf97 --- /dev/null +++ b/UefiPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c @@ -0,0 +1,127 @@ +/** @file + Set TPM device type + + In SecurityPkg, this module initializes the TPM device type based on a UEFI + variable and/or hardware detection. In OvmfPkg, the module only performs TPM2 + hardware detection. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ Copyright (C) 2018, Red Hat, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +STATIC CONST EFI_PEI_PPI_DESCRIPTOR mTpmSelectedPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiTpmDeviceSelectedGuid, + NULL +}; + +STATIC CONST EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiTpmInitializationDonePpiGuid, + NULL +}; + +#pragma pack (1) + +typedef struct { + TPM_RSP_COMMAND_HDR Hdr; + TPM_CURRENT_TICKS CurrentTicks; +} TPM_RSP_GET_TICKS; + +#pragma pack () + +static +EFI_STATUS +TestTpm12 ( + ) +{ + EFI_STATUS Status; + TPM_RQU_COMMAND_HDR Command; + TPM_RSP_GET_TICKS Response; + UINT32 Length; + + Command.tag = SwapBytes16 (TPM_TAG_RQU_COMMAND); + Command.paramSize = SwapBytes32 (sizeof (Command)); + Command.ordinal = SwapBytes32 (TPM_ORD_GetTicks); + + Length = sizeof (Response); + Status = Tpm12SubmitCommand (sizeof (Command), (UINT8 *)&Command, &Length, (UINT8 *)&Response); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +/** + The entry point for Tcg2 configuration driver. + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. +**/ +EFI_STATUS +EFIAPI +Tcg2ConfigPeimEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + UINTN Size; + EFI_STATUS Status; + + Status = Tpm2RequestUseTpm (); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a: TPM2 detected\n", __FUNCTION__)); + Size = sizeof (gEfiTpmDeviceInstanceTpm20DtpmGuid); + Status = PcdSetPtrS ( + PcdTpmInstanceGuid, + &Size, + &gEfiTpmDeviceInstanceTpm20DtpmGuid + ); + ASSERT_EFI_ERROR (Status); + } else { + Status = Tpm12RequestUseTpm (); + if (!EFI_ERROR (Status) && !EFI_ERROR (TestTpm12 ())) { + DEBUG ((DEBUG_INFO, "%a: TPM1.2 detected\n", __FUNCTION__)); + Size = sizeof (gEfiTpmDeviceInstanceTpm12Guid); + Status = PcdSetPtrS ( + PcdTpmInstanceGuid, + &Size, + &gEfiTpmDeviceInstanceTpm12Guid + ); + ASSERT_EFI_ERROR (Status); + } else { + DEBUG ((DEBUG_INFO, "%a: no TPM detected\n", __FUNCTION__)); + // + // If no TPM2 was detected, we still need to install + // TpmInitializationDonePpi. Namely, Tcg2Pei will exit early upon seeing + // the default (all-bits-zero) contents of PcdTpmInstanceGuid, thus we have + // to install the PPI in its place, in order to unblock any dependent + // PEIMs. + // + Status = PeiServicesInstallPpi (&mTpmInitializationDonePpiList); + ASSERT_EFI_ERROR (Status); + } + } + + // + // Selection done + // + Status = PeiServicesInstallPpi (&mTpmSelectedPpi); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/UefiPayloadPkg/UefiPayloadPkg.fdf b/UefiPayloadPkg/UefiPayloadPkg.fdf index ee3209c98f..a154f0ddd9 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.fdf +++ b/UefiPayloadPkg/UefiPayloadPkg.fdf @@ -11,15 +11,15 @@ ################################################################################ [FD.UefiPayload] BaseAddress = 0x800000|gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase -Size = 0x410000|gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize +Size = 0x800000|gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize ErasePolarity = 1 BlockSize = 0x1000 -NumBlocks = 0x410 +NumBlocks = 0x800 -0x00000000|0x030000 +0x00000000|0x040000 FV = PEIFV -0x00030000|0x3E0000 +0x00040000|0x7C0000 FV = DXEFV ################################################################################ @@ -51,6 +51,12 @@ INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf INF UefiPayloadPkg/BlSupportPei/BlSupportPei.inf INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +!if $(TPM_ENABLE) == TRUE +INF UefiPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf +INF SecurityPkg/Tcg/TcgPei/TcgPei.inf +INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf +!endif + ################################################################################ [FV.DXEFV] @@ -194,6 +200,11 @@ INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf +!if $(TPM_ENABLE) == TRUE +INF SecurityPkg/Tcg/TcgDxe/TcgDxe.inf +INF SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf +INF SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf +!endif # # Shell diff --git a/UefiPayloadPkg/UefiPayloadPkgIa32.dsc b/UefiPayloadPkg/UefiPayloadPkgIa32.dsc index 8c5d86bf98..4b7e7786a5 100644 --- a/UefiPayloadPkg/UefiPayloadPkgIa32.dsc +++ b/UefiPayloadPkg/UefiPayloadPkgIa32.dsc @@ -87,6 +87,11 @@ # DEFINE SHELL_TYPE = BUILD_SHELL + # + # Security options: + # + DEFINE TPM_ENABLE = TRUE + [BuildOptions] *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES GCC:*_UNIXGCC_*_CC_FLAGS = -DMDEPKG_NDEBUG @@ -217,6 +222,14 @@ TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf +!if $(TPM_ENABLE) == TRUE + Tpm12CommandLib|SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf + Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf + Tcg2PhysicalPresenceLib|SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf + Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf + TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf +!endif + [LibraryClasses.IA32.SEC] DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf @@ -235,6 +248,13 @@ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf !endif +[LibraryClasses.common.PEIM] +!if $(TPM_ENABLE) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf +!endif + [LibraryClasses.common.DXE_CORE] PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf @@ -370,6 +390,8 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|31 gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|100 + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + ################################################################################ # # Components Section - list of all EDK II Modules needed by this Platform. @@ -399,6 +421,20 @@ UefiPayloadPkg/BlSupportPei/BlSupportPei.inf MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +!if $(TPM_ENABLE) == TRUE + UefiPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf + SecurityPkg/Tcg/TcgPei/TcgPei.inf + SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf { + + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf + NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf + NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf + NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf + } +!endif + [Components.IA32] # # DXE Core @@ -411,7 +447,14 @@ # # Components that produce the architectural protocols # - MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf { + +!if $(TPM_ENABLE) == TRUE + NULL|SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf + NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf +!endif + } + UefiCpuPkg/CpuDxe/CpuDxe.inf MdeModulePkg/Universal/BdsDxe/BdsDxe.inf MdeModulePkg/Logo/LogoDxe.inf @@ -522,6 +565,28 @@ UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf +!if $(TPM_ENABLE) == TRUE + SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf { + + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf + NULL|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf + NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf + NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf + NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf + } + SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf { + + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf + } + SecurityPkg/Tcg/TcgDxe/TcgDxe.inf { + + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf + } +!endif + #------------------------------ # Build the shell #------------------------------ diff --git a/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc b/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc index 9c91c9f16c..c1c6638c94 100644 --- a/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc +++ b/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc @@ -87,6 +87,11 @@ # DEFINE SHELL_TYPE = BUILD_SHELL + # + # Security options: + # + DEFINE TPM_ENABLE = TRUE + [BuildOptions] *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES GCC:*_UNIXGCC_*_CC_FLAGS = -DMDEPKG_NDEBUG @@ -217,6 +222,16 @@ TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf +!if $(TPM_ENABLE) == TRUE + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf + Tpm12CommandLib|SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf + Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf + Tcg2PhysicalPresenceLib|SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf + Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf + TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf +!endif + [LibraryClasses.IA32.SEC] DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf @@ -235,6 +250,13 @@ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf !endif +[LibraryClasses.common.PEIM] +!if $(TPM_ENABLE) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf +!endif + [LibraryClasses.common.DXE_CORE] PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf @@ -245,6 +267,9 @@ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf !endif CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf +!if $(TPM_ENABLE) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf +!endif [LibraryClasses.common.DXE_DRIVER] PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf @@ -257,6 +282,9 @@ !endif CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf +!if $(TPM_ENABLE) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf +!endif [LibraryClasses.common.DXE_RUNTIME_DRIVER] PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf @@ -371,6 +399,8 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|31 gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|100 + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + ################################################################################ # # Components Section - list of all EDK II Modules needed by this Platform. @@ -400,6 +430,20 @@ UefiPayloadPkg/BlSupportPei/BlSupportPei.inf MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +!if $(TPM_ENABLE) == TRUE + UefiPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf + SecurityPkg/Tcg/TcgPei/TcgPei.inf + SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf { + + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf + NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf + NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf + NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf + } +!endif + [Components.X64] # # DXE Core @@ -412,7 +456,14 @@ # # Components that produce the architectural protocols # - MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf { + +!if $(TPM_ENABLE) == TRUE + NULL|SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf + NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf +!endif + } + UefiCpuPkg/CpuDxe/CpuDxe.inf MdeModulePkg/Universal/BdsDxe/BdsDxe.inf MdeModulePkg/Logo/LogoDxe.inf @@ -523,6 +574,28 @@ UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf +!if $(TPM_ENABLE) == TRUE + SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf { + + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf + NULL|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf + NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf + NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf + NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf + } + SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf { + + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf + } + SecurityPkg/Tcg/TcgDxe/TcgDxe.inf { + + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf + } +!endif + #------------------------------ # Build the shell #------------------------------