--- /dev/null
+/** @file\r
+Provides a secure platform-specific method to detect physically present user.\r
+\r
+Copyright (c) 2013 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Library/PlatformHelperLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/I2cLib.h>\r
+\r
+#include <PlatformBoards.h>\r
+#include <Pcal9555.h>\r
+#include <QNCAccess.h>\r
+\r
+//\r
+// Global variable to cache pointer to I2C protocol.\r
+//\r
+EFI_PLATFORM_TYPE mPlatformType = TypeUnknown;\r
+\r
+BOOLEAN\r
+CheckResetButtonState (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_I2C_DEVICE_ADDRESS I2CSlaveAddress;\r
+ UINTN Length;\r
+ UINTN ReadLength;\r
+ UINT8 Buffer[2];\r
+\r
+ DEBUG ((EFI_D_ERROR, "CheckResetButtonState(): mPlatformType == %d\n", mPlatformType));\r
+ if (mPlatformType == GalileoGen2) {\r
+ //\r
+ // Reset Button - EXP2.P1_7 should be configured as an input.\r
+ //\r
+ PlatformPcal9555GpioSetDir (\r
+ GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR, // IO Expander 2.\r
+ 15, // P1-7.\r
+ FALSE\r
+ );\r
+\r
+ //\r
+ // Reset Button - EXP2.P1_7 pullup should be disabled.\r
+ //\r
+ PlatformPcal9555GpioDisablePull (\r
+ GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR, // IO Expander 2.\r
+ 15 // P1-7.\r
+ );\r
+\r
+ //\r
+ // Read state of Reset Button - EXP2.P1_7\r
+ // This GPIO is pulled high when the button is not pressed\r
+ // This GPIO reads low when button is pressed\r
+ //\r
+ return PlatformPcal9555GpioGetState (\r
+ GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR, // IO Expander 2.\r
+ 15 // P1-7.\r
+ );\r
+ }\r
+ if (mPlatformType == Galileo) {\r
+ //\r
+ // Detect the I2C Slave Address of the GPIO Expander\r
+ //\r
+ if (PlatformLegacyGpioGetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_DETERMINE_IOEXP_SLA_RESUMEWELL_GPIO)) {\r
+ I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2HI_7BIT_SLAVE_ADDR;\r
+ } else {\r
+ I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2LO_7BIT_SLAVE_ADDR;\r
+ }\r
+\r
+ //\r
+ // Select Port 5\r
+ //\r
+ Length = 2;\r
+ Buffer[0] = 0x18;\r
+ Buffer[1] = 0x05;\r
+ Status = I2cWriteMultipleByte (\r
+ I2CSlaveAddress,\r
+ EfiI2CSevenBitAddrMode,\r
+ &Length,\r
+ &Buffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Read "Pin Direction" of Port 5\r
+ //\r
+ Length = 1;\r
+ ReadLength = 1;\r
+ Buffer[1] = 0x1C;\r
+ Status = I2cReadMultipleByte (\r
+ I2CSlaveAddress,\r
+ EfiI2CSevenBitAddrMode,\r
+ &Length,\r
+ &ReadLength,\r
+ &Buffer[1]\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Set "Pin Direction" of Port 5, Bit 0 as input\r
+ //\r
+ Length = 2;\r
+ Buffer[0] = 0x1C;\r
+ Buffer[1] = Buffer[1] | BIT0;\r
+\r
+ Status = I2cWriteMultipleByte (\r
+ I2CSlaveAddress,\r
+ EfiI2CSevenBitAddrMode,\r
+ &Length,\r
+ &Buffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Read Port 5\r
+ //\r
+ Buffer[1] = 5;\r
+ Length = 1;\r
+ ReadLength = 1;\r
+\r
+ Status = I2cReadMultipleByte (\r
+ I2CSlaveAddress,\r
+ EfiI2CSevenBitAddrMode,\r
+ &Length,\r
+ &ReadLength,\r
+ &Buffer[1]\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Return the state of Port 5, Bit 0\r
+ //\r
+ return ((Buffer[1] & BIT0) != 0);\r
+ }\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+\r
+ This function provides a platform-specific method to detect whether the platform\r
+ is operating by a physically present user.\r
+\r
+ Programmatic changing of platform security policy (such as disable Secure Boot,\r
+ or switch between Standard/Custom Secure Boot mode) MUST NOT be possible during\r
+ Boot Services or after exiting EFI Boot Services. Only a physically present user\r
+ is allowed to perform these operations.\r
+\r
+ NOTE THAT: This function cannot depend on any EFI Variable Service since they are\r
+ not available when this function is called in AuthenticateVariable driver.\r
+\r
+ @retval TRUE The platform is operated by a physically present user.\r
+ @retval FALSE The platform is NOT operated by a physically present user.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+UserPhysicalPresent (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // If user has already been detected as present, then return TRUE\r
+ //\r
+ if (PcdGetBool (PcdUserIsPhysicallyPresent)) {\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // Check to see if user is present now\r
+ //\r
+ if (CheckResetButtonState ()) {\r
+ //\r
+ // User is still not present, then return FALSE\r
+ //\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // User has gone from not present to present state, so set\r
+ // PcdUserIsPhysicallyPresent to TRUE\r
+ //\r
+ Status = PcdSetBoolS (PcdUserIsPhysicallyPresent, TRUE);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Determines if a user is physically present by reading the reset button state.\r
+\r
+ @param ImageHandle The image handle of this driver.\r
+ @param SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS Install the Secure Boot Helper Protocol successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PlatformSecureLibInitialize (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Get the platform type\r
+ //\r
+ mPlatformType = (EFI_PLATFORM_TYPE)PcdGet16 (PcdPlatformType);\r
+\r
+ //\r
+ // Read the state of the reset button when the library is initialized\r
+ //\r
+ Status = PcdSetBoolS (PcdUserIsPhysicallyPresent, !CheckResetButtonState ());\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return EFI_SUCCESS;\r
+}\r