/** @file The functions for access policy modification. Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #include "UserProfileManager.h" /** Collect all the access policy data to mUserInfo.AccessPolicy, and save it to user profile. **/ VOID SaveAccessPolicy ( VOID ) { EFI_STATUS Status; UINTN OffSet; UINTN Size; EFI_USER_INFO_ACCESS_CONTROL Control; EFI_USER_INFO_HANDLE UserInfo; EFI_USER_INFO *Info; if (mUserInfo.AccessPolicy != NULL) { FreePool (mUserInfo.AccessPolicy); } mUserInfo.AccessPolicy = NULL; mUserInfo.AccessPolicyLen = 0; mUserInfo.AccessPolicyModified = TRUE; OffSet = 0; // // Save access right. // Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL); if (mUserInfo.AccessPolicyLen - OffSet < Size) { ExpandMemory (OffSet, Size); } Control.Type = mAccessInfo.AccessRight; Control.Size = (UINT32) Size; CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control)); OffSet += sizeof (Control); // // Save access setup. // Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + sizeof (EFI_GUID); if (mUserInfo.AccessPolicyLen - OffSet < Size) { ExpandMemory (OffSet, Size); } Control.Type = EFI_USER_INFO_ACCESS_SETUP; Control.Size = (UINT32) Size; CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control)); OffSet += sizeof (Control); if (mAccessInfo.AccessSetup == ACCESS_SETUP_NORMAL) { CopyGuid ((EFI_GUID *) (mUserInfo.AccessPolicy + OffSet), &gEfiUserInfoAccessSetupNormalGuid); } else if (mAccessInfo.AccessSetup == ACCESS_SETUP_RESTRICTED) { CopyGuid ((EFI_GUID *) (mUserInfo.AccessPolicy + OffSet), &gEfiUserInfoAccessSetupRestrictedGuid); } else if (mAccessInfo.AccessSetup == ACCESS_SETUP_ADMIN) { CopyGuid ((EFI_GUID *) (mUserInfo.AccessPolicy + OffSet), &gEfiUserInfoAccessSetupAdminGuid); } OffSet += sizeof (EFI_GUID); // // Save access of boot order. // Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + sizeof (UINT32); if (mUserInfo.AccessPolicyLen - OffSet < Size) { ExpandMemory (OffSet, Size); } Control.Type = EFI_USER_INFO_ACCESS_BOOT_ORDER; Control.Size = (UINT32) Size; CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control)); OffSet += sizeof (Control); CopyMem ((UINT8 *) (mUserInfo.AccessPolicy + OffSet), &mAccessInfo.AccessBootOrder, sizeof (UINT32)); OffSet += sizeof (UINT32); // // Save permit load. // if (mAccessInfo.LoadPermitLen > 0) { Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + mAccessInfo.LoadPermitLen; if (mUserInfo.AccessPolicyLen - OffSet < Size) { ExpandMemory (OffSet, Size); } Control.Type = EFI_USER_INFO_ACCESS_PERMIT_LOAD; Control.Size = (UINT32) Size; CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control)); OffSet += sizeof (Control); CopyMem (mUserInfo.AccessPolicy + OffSet, mAccessInfo.LoadPermit, mAccessInfo.LoadPermitLen); OffSet += mAccessInfo.LoadPermitLen; } // // Save forbid load. // if (mAccessInfo.LoadForbidLen > 0) { Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + mAccessInfo.LoadForbidLen; if (mUserInfo.AccessPolicyLen - OffSet < Size) { ExpandMemory (OffSet, Size); } Control.Type = EFI_USER_INFO_ACCESS_FORBID_LOAD; Control.Size = (UINT32) Size; CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control)); OffSet += sizeof (Control); CopyMem (mUserInfo.AccessPolicy + OffSet, mAccessInfo.LoadForbid, mAccessInfo.LoadForbidLen); OffSet += mAccessInfo.LoadForbidLen; } // // Save permit connect. // if (mAccessInfo.ConnectPermitLen > 0) { Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + mAccessInfo.ConnectPermitLen; if (mUserInfo.AccessPolicyLen - OffSet < Size) { ExpandMemory (OffSet, Size); } Control.Type = EFI_USER_INFO_ACCESS_PERMIT_CONNECT; Control.Size = (UINT32) Size; CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control)); OffSet += sizeof (Control); CopyMem (mUserInfo.AccessPolicy + OffSet, mAccessInfo.ConnectPermit, mAccessInfo.ConnectPermitLen); OffSet += mAccessInfo.ConnectPermitLen; } // // Save forbid connect. // if (mAccessInfo.ConnectForbidLen > 0) { Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + mAccessInfo.ConnectForbidLen; if (mUserInfo.AccessPolicyLen - OffSet < Size) { ExpandMemory (OffSet, Size); } Control.Type = EFI_USER_INFO_ACCESS_FORBID_CONNECT; Control.Size = (UINT32) Size; CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control)); OffSet += sizeof (Control); CopyMem (mUserInfo.AccessPolicy + OffSet, mAccessInfo.ConnectForbid, mAccessInfo.ConnectForbidLen); OffSet += mAccessInfo.ConnectForbidLen; } mUserInfo.AccessPolicyLen = OffSet; // // Save access policy. // if (mUserInfo.AccessPolicyModified && (mUserInfo.AccessPolicyLen > 0) && (mUserInfo.AccessPolicy != NULL)) { Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + mUserInfo.AccessPolicyLen); if (Info == NULL) { return ; } Status = FindInfoByType (mModifyUser, EFI_USER_INFO_ACCESS_POLICY_RECORD, &UserInfo); if (!EFI_ERROR (Status)) { Info->InfoType = EFI_USER_INFO_ACCESS_POLICY_RECORD; Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; Info->InfoSize = (UINT32) (sizeof (EFI_USER_INFO) + mUserInfo.AccessPolicyLen); CopyMem ((UINT8 *) (Info + 1), mUserInfo.AccessPolicy, mUserInfo.AccessPolicyLen); Status = mUserManager->SetInfo ( mUserManager, mModifyUser, &UserInfo, Info, Info->InfoSize ); mUserInfo.AccessPolicyModified = FALSE; } FreePool (Info); } if (mAccessInfo.ConnectForbid != NULL) { FreePool (mAccessInfo.ConnectForbid); mAccessInfo.ConnectForbid = NULL; } if (mAccessInfo.ConnectPermit != NULL) { FreePool (mAccessInfo.ConnectPermit); mAccessInfo.ConnectPermit = NULL; } if (mAccessInfo.LoadForbid != NULL) { FreePool (mAccessInfo.LoadForbid); mAccessInfo.LoadForbid = NULL; } if (mAccessInfo.LoadPermit != NULL) { FreePool (mAccessInfo.LoadPermit); mAccessInfo.LoadPermit = NULL; } } /** Create an action OpCode with QuestionID and DevicePath on a given OpCodeHandle. @param[in] QuestionID The question ID. @param[in] DevicePath Points to device path. @param[in] OpCodeHandle Points to container for dynamic created opcodes. **/ VOID AddDevicePath ( IN UINTN QuestionID, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN VOID *OpCodeHandle ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *Next; EFI_STRING_ID NameID; EFI_STRING DriverName; EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathText; // // Locate device path to text protocol. // Status = gBS->LocateProtocol ( &gEfiDevicePathToTextProtocolGuid, NULL, (VOID **) &DevicePathText ); if (EFI_ERROR (Status)) { return ; } // // Get driver file name node. // Next = DevicePath; while (!IsDevicePathEnd (Next)) { DevicePath = Next; Next = NextDevicePathNode (Next); } // // Display the device path in form. // DriverName = DevicePathText->ConvertDevicePathToText (DevicePath, FALSE, FALSE); NameID = HiiSetString (mCallbackInfo->HiiHandle, 0, DriverName, NULL); FreePool (DriverName); if (NameID == 0) { return ; } HiiCreateActionOpCode ( OpCodeHandle, // Container for dynamic created opcodes (UINT16) QuestionID, // Question ID NameID, // Prompt text STRING_TOKEN (STR_NULL_STRING), // Help text EFI_IFR_FLAG_CALLBACK, // Question flag 0 // Action String ID ); } /** Check whether the DevicePath is in the device path forbid list (mAccessInfo.LoadForbid). @param[in] DevicePath Points to device path. @retval TRUE The DevicePath is in the device path forbid list. @retval FALSE The DevicePath is not in the device path forbid list. **/ BOOLEAN IsLoadForbidden ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { UINTN OffSet; UINTN DPSize; UINTN Size; EFI_DEVICE_PATH_PROTOCOL *Dp; OffSet = 0; Size = GetDevicePathSize (DevicePath); // // Check each device path. // while (OffSet < mAccessInfo.LoadForbidLen) { Dp = (EFI_DEVICE_PATH_PROTOCOL *) (mAccessInfo.LoadForbid + OffSet); DPSize = GetDevicePathSize (Dp); // // Compare device path. // if ((DPSize == Size) && (CompareMem (DevicePath, Dp, Size) == 0)) { return TRUE; } OffSet += DPSize; } return FALSE; } /** Display the permit load device path in the loadable device path list. **/ VOID DisplayLoadPermit( VOID ) { EFI_STATUS Status; CHAR16 *Order; UINTN OrderSize; UINTN ListCount; UINTN Index; UINT8 *Var; UINT8 *VarPtr; CHAR16 VarName[12]; VOID *StartOpCodeHandle; VOID *EndOpCodeHandle; EFI_IFR_GUID_LABEL *StartLabel; EFI_IFR_GUID_LABEL *EndLabel; // // Get DriverOrder. // OrderSize = 0; Status = gRT->GetVariable ( L"DriverOrder", &gEfiGlobalVariableGuid, NULL, &OrderSize, NULL ); if (Status != EFI_BUFFER_TOO_SMALL) { return ; } Order = AllocateZeroPool (OrderSize); if (Order == NULL) { return ; } Status = gRT->GetVariable ( L"DriverOrder", &gEfiGlobalVariableGuid, NULL, &OrderSize, Order ); if (EFI_ERROR (Status)) { return ; } // // Initialize the container for dynamic opcodes. // StartOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (StartOpCodeHandle != NULL); EndOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (EndOpCodeHandle != NULL); // // Create Hii Extend Label OpCode. // StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL) ); StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; StartLabel->Number = LABEL_PERMIT_LOAD_FUNC; EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL) ); EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; EndLabel->Number = LABEL_END; // // Add each driver option. // Var = NULL; ListCount = OrderSize / sizeof (UINT16); for (Index = 0; Index < ListCount; Index++) { // // Get driver device path. // UnicodeSPrint (VarName, sizeof (VarName), L"Driver%04x", Order[Index]); Var = GetEfiGlobalVariable (VarName); if (Var == NULL) { continue; } // // Check whether the driver is already forbidden. // VarPtr = Var; // // Skip attribute. // VarPtr += sizeof (UINT32); // // Skip device path lenth. // VarPtr += sizeof (UINT16); // // Skip descript string. // VarPtr += StrSize ((UINT16 *) VarPtr); if (IsLoadForbidden ((EFI_DEVICE_PATH_PROTOCOL *) VarPtr)) { FreePool (Var); Var = NULL; continue; } AddDevicePath ( KEY_MODIFY_USER | KEY_MODIFY_AP_DP | KEY_LOAD_PERMIT_MODIFY | Order[Index], (EFI_DEVICE_PATH_PROTOCOL *) VarPtr, StartOpCodeHandle ); FreePool (Var); Var = NULL; } HiiUpdateForm ( mCallbackInfo->HiiHandle, // HII handle &gUserProfileManagerGuid, // Formset GUID FORMID_PERMIT_LOAD_DP, // Form ID StartOpCodeHandle, // Label for where to insert opcodes EndOpCodeHandle // Replace data ); HiiFreeOpCodeHandle (StartOpCodeHandle); HiiFreeOpCodeHandle (EndOpCodeHandle); // // Clear Environment. // if (Var != NULL) { FreePool (Var); } FreePool (Order); } /** Display the forbid load device path list (mAccessInfo.LoadForbid). **/ VOID DisplayLoadForbid ( VOID ) { UINTN Offset; UINTN DPSize; UINTN Index; EFI_DEVICE_PATH_PROTOCOL *Dp; VOID *StartOpCodeHandle; VOID *EndOpCodeHandle; EFI_IFR_GUID_LABEL *StartLabel; EFI_IFR_GUID_LABEL *EndLabel; // // Initialize the container for dynamic opcodes. // StartOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (StartOpCodeHandle != NULL); EndOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (EndOpCodeHandle != NULL); // // Create Hii Extend Label OpCode. // StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL) ); StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; StartLabel->Number = LABLE_FORBID_LOAD_FUNC; EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL) ); EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; EndLabel->Number = LABEL_END; // // Add each forbid load drivers. // Offset = 0; Index = 0; while (Offset < mAccessInfo.LoadForbidLen) { Dp = (EFI_DEVICE_PATH_PROTOCOL *) (mAccessInfo.LoadForbid + Offset); DPSize = GetDevicePathSize (Dp); AddDevicePath ( KEY_MODIFY_USER | KEY_MODIFY_AP_DP | KEY_LOAD_FORBID_MODIFY | Index, Dp, StartOpCodeHandle ); Index++; Offset += DPSize; } HiiUpdateForm ( mCallbackInfo->HiiHandle, // HII handle &gUserProfileManagerGuid, // Formset GUID FORMID_FORBID_LOAD_DP, // Form ID StartOpCodeHandle, // Label for where to insert opcodes EndOpCodeHandle // Replace data ); HiiFreeOpCodeHandle (StartOpCodeHandle); HiiFreeOpCodeHandle (EndOpCodeHandle); } /** Display the permit connect device path. **/ VOID DisplayConnectPermit ( VOID ) { // // Note: // As no architect protocol/interface to be called in ConnectController() // to verify the device path, just add a place holder for permitted connect // device path. // } /** Display the forbid connect device path list. **/ VOID DisplayConnectForbid ( VOID ) { // // Note: // As no architect protocol/interface to be called in ConnectController() // to verify the device path, just add a place holder for forbidden connect // device path. // } /** Delete the specified device path by DriverIndex from the forbid device path list (mAccessInfo.LoadForbid). @param[in] DriverIndex The index of driver in forbidden device path list. **/ VOID DeleteFromForbidLoad ( IN UINT16 DriverIndex ) { UINTN OffSet; UINTN DPSize; UINTN OffLen; EFI_DEVICE_PATH_PROTOCOL *Dp; OffSet = 0; // // Find the specified device path. // while ((OffSet < mAccessInfo.LoadForbidLen) && (DriverIndex > 0)) { Dp = (EFI_DEVICE_PATH_PROTOCOL *) (mAccessInfo.LoadForbid + OffSet); DPSize = GetDevicePathSize (Dp); OffSet += DPSize; DriverIndex--; } // // Specified device path found. // if (DriverIndex == 0) { Dp = (EFI_DEVICE_PATH_PROTOCOL *) (mAccessInfo.LoadForbid + OffSet); DPSize = GetDevicePathSize (Dp); OffLen = mAccessInfo.LoadForbidLen - OffSet - DPSize; if (OffLen > 0) { CopyMem ( mAccessInfo.LoadForbid + OffSet, mAccessInfo.LoadForbid + OffSet + DPSize, OffLen ); } mAccessInfo.LoadForbidLen -= DPSize; } } /** Add the specified device path by DriverIndex to the forbid device path list (mAccessInfo.LoadForbid). @param[in] DriverIndex The index of driver saved in driver options. **/ VOID AddToForbidLoad ( IN UINT16 DriverIndex ) { UINTN DevicePathLen; UINT8 *Var; UINT8 *VarPtr; UINTN NewLen; UINT8 *NewFL; CHAR16 VarName[13]; // // Get loadable driver device path. // UnicodeSPrint (VarName, sizeof (VarName), L"Driver%04x", DriverIndex); Var = GetEfiGlobalVariable (VarName); if (Var == NULL) { return; } // // Save forbid load driver. // VarPtr = Var; // // Skip attribute. // VarPtr += sizeof (UINT32); DevicePathLen = *(UINT16 *) VarPtr; // // Skip device path length. // VarPtr += sizeof (UINT16); // // Skip description string. // VarPtr += StrSize ((UINT16 *) VarPtr); NewLen = mAccessInfo.LoadForbidLen + DevicePathLen; NewFL = AllocateZeroPool (NewLen); if (NewFL == NULL) { FreePool (Var); return ; } if (mAccessInfo.LoadForbidLen > 0) { CopyMem (NewFL, mAccessInfo.LoadForbid, mAccessInfo.LoadForbidLen); FreePool (mAccessInfo.LoadForbid); } CopyMem (NewFL + mAccessInfo.LoadForbidLen, VarPtr, DevicePathLen); mAccessInfo.LoadForbidLen = NewLen; mAccessInfo.LoadForbid = NewFL; FreePool (Var); }