pub fn from_raw(raw_var_policy_header: *const RawVariablePolicyEntry) -> Result<Self, efi::Status> {
    if raw_var_policy_header.is_null() {
      return Err(efi::Status::INVALID_PARAMETER);
    }

    let mut new_policy = VariablePolicyEntry {
      min_size: Self::NO_MIN_SIZE, max_size: Self::NO_MAX_SIZE,
      attr_must_have: Self::NO_MUST_ATTR, attr_cant_have: Self::NO_CANT_ATTR,
      lock_policy_type: LockPolicyType::NoLock,
      namespace: efi::Guid::from_fields(0, 0, 0, 0, 0, &[0, 0, 0, 0, 0, 0]),
      name: None
    };

    // Validate the first few fields of the structure.
    // If the header looks valid, start grabbing fields.
    unsafe {
      // Sanitize some quick values.
      if (*raw_var_policy_header).version != VariablePolicyEntry::RAW_ENTRY_REVISION ||
          ((*raw_var_policy_header).size as usize) < RAW_VARIABLE_POLICY_ENTRY_SIZE ||
          (*raw_var_policy_header).size < (*raw_var_policy_header).offset_to_name {
            return Err(efi::Status::INVALID_PARAMETER);
          }

      new_policy.min_size = (*raw_var_policy_header).min_size;
      new_policy.max_size = (*raw_var_policy_header).max_size;
      new_policy.attr_must_have = (*raw_var_policy_header).attr_must_have;
      new_policy.attr_cant_have = (*raw_var_policy_header).attr_cant_have;
      new_policy.namespace = (*raw_var_policy_header).namespace;

      let data_buffer = raw_var_policy_header as *const u8;
      let entry_end = data_buffer.offset((*raw_var_policy_header).size as isize) as usize;

      // Check for the valid list of lock policies.
      new_policy.lock_policy_type = match (*raw_var_policy_header).lock_policy_type {
        RawLockPolicyType::NO_LOCK => LockPolicyType::NoLock,
        RawLockPolicyType::LOCK_NOW => LockPolicyType::LockNow,
        RawLockPolicyType::LOCK_ON_CREATE => LockPolicyType::LockOnCreate,
        RawLockPolicyType::LOCK_ON_VAR_STATE => {
          let raw_var_state_header = data_buffer
                                        .add(RAW_VARIABLE_POLICY_ENTRY_SIZE)
                                        as *const RawVarStateLock;

          // If the policy type is VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE, make sure that the matching state variable Name
          // terminates before the OffsetToName for the matching policy variable Name.
          let mut string_len: isize   = 0;
          let state_name_string = (raw_var_state_header as *const u8)
                                    .add(RAW_VAR_STATE_LOCK_SIZE)
                                    as *const u16;
          while *(state_name_string.offset(string_len)) != 0 {
            if entry_end <= state_name_string.offset(string_len) as usize {
              return Err(efi::Status::INVALID_PARAMETER);
            }
            string_len += 1;
          }

          // At this point we should have either exeeded the structure or be pointing at the last char in LockPolicy->Name.
          // We should check to make sure that the policy Name comes immediately after this charcter.
          if state_name_string.offset(string_len+1) as usize !=
              data_buffer.offset((*raw_var_policy_header).offset_to_name as isize) as usize {
            return Err(efi::Status::INVALID_PARAMETER);
          }

          LockPolicyType::LockOnVarState(VarStateLock {
            namespace: (*raw_var_state_header).namespace,
            value: (*raw_var_state_header).value,
            name: String::from_utf16_lossy(slice::from_raw_parts(state_name_string, string_len as usize)),
          })
        },
        _ => return Err(efi::Status::INVALID_PARAMETER)
      };

      // Make sure that OffsetToName is exactly sizeof(VARIABLE_POLICY_ENTRY) if not VarState.
      // TODO: Find a better way to do this.
      if let LockPolicyType::LockOnVarState(_) = new_policy.lock_policy_type {
      }
      else if (*raw_var_policy_header).offset_to_name != RAW_VARIABLE_POLICY_ENTRY_SIZE as u16 {
          return Err(efi::Status::INVALID_PARAMETER);
      }

      // Check to make sure that the name has a terminating character
      // before the end of the structure.
      // We've already checked that the name is within the bounds of the structure.
      if (*raw_var_policy_header).size != (*raw_var_policy_header).offset_to_name {
        let mut string_len: isize = 0;
        let name_string = (raw_var_policy_header as *const u8)
                            .offset((*raw_var_policy_header).offset_to_name as isize)
                            as *const u16;
        while *(name_string.offset(string_len)) != 0 {
          if entry_end <= name_string.offset(string_len) as usize {
            return Err(efi::Status::INVALID_PARAMETER);
          }
          string_len += 1;
        }

        // Finally, we should be pointed at the very last character in Name, so we should be right
        // up against the end of the structure.
        if name_string.offset(string_len+1) as usize != entry_end {
          return Err(efi::Status::INVALID_PARAMETER);
        }

        new_policy.name = Some(
          String::from_utf16_lossy(slice::from_raw_parts(name_string, string_len as usize))
          );
      }
    }

    if new_policy.is_valid() {
      Ok(new_policy)
    }
    else {
      Err(efi::Status::INVALID_PARAMETER)
    }
  }
// TODO: Have this return specific error codes, rather than EFI codes.
//       Can map to EFI codes in the caller, if it's an EFI interface.
Have this return specific error codes, rather than EFI codes.
Can map to EFI codes in the caller, if it's an EFI interface.
Have this return specific error codes rather than EFI codes . Can map to EFI codes in the caller if it ' s an EFI interface .
pub fn from_raw(raw_var_policy_header: *const RawVariablePolicyEntry) -> Result<Self, efi::Status> {
    if raw_var_policy_header.is_null() {
      return Err(efi::Status::INVALID_PARAMETER);
    }
    let mut new_policy = VariablePolicyEntry {
      min_size: Self::NO_MIN_SIZE, max_size: Self::NO_MAX_SIZE,
      attr_must_have: Self::NO_MUST_ATTR, attr_cant_have: Self::NO_CANT_ATTR,
      lock_policy_type: LockPolicyType::NoLock,
      namespace: efi::Guid::from_fields(0, 0, 0, 0, 0, &[0, 0, 0, 0, 0, 0]),
      name: None
    };
    // Validate the first few fields of the structure.
    // If the header looks valid, start grabbing fields.
    unsafe {
      // Sanitize some quick values.
      if (*raw_var_policy_header).version != VariablePolicyEntry::RAW_ENTRY_REVISION ||
          ((*raw_var_policy_header).size as usize) < RAW_VARIABLE_POLICY_ENTRY_SIZE ||
          (*raw_var_policy_header).size < (*raw_var_policy_header).offset_to_name {
            return Err(efi::Status::INVALID_PARAMETER);
          }
      new_policy.min_size = (*raw_var_policy_header).min_size;
      new_policy.max_size = (*raw_var_policy_header).max_size;
      new_policy.attr_must_have = (*raw_var_policy_header).attr_must_have;
      new_policy.attr_cant_have = (*raw_var_policy_header).attr_cant_have;
      new_policy.namespace = (*raw_var_policy_header).namespace;
      let data_buffer = raw_var_policy_header as *const u8;
      let entry_end = data_buffer.offset((*raw_var_policy_header).size as isize) as usize;
      // Check for the valid list of lock policies.
      new_policy.lock_policy_type = match (*raw_var_policy_header).lock_policy_type {
        RawLockPolicyType::NO_LOCK => LockPolicyType::NoLock,
        RawLockPolicyType::LOCK_NOW => LockPolicyType::LockNow,
        RawLockPolicyType::LOCK_ON_CREATE => LockPolicyType::LockOnCreate,
        RawLockPolicyType::LOCK_ON_VAR_STATE => {
          let raw_var_state_header = data_buffer
                                        .add(RAW_VARIABLE_POLICY_ENTRY_SIZE)
                                        as *const RawVarStateLock;
          // If the policy type is VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE, make sure that the matching state variable Name
          // terminates before the OffsetToName for the matching policy variable Name.
          let mut string_len: isize   = 0;
          let state_name_string = (raw_var_state_header as *const u8)
                                    .add(RAW_VAR_STATE_LOCK_SIZE)
                                    as *const u16;
          while *(state_name_string.offset(string_len)) != 0 {
            if entry_end <= state_name_string.offset(string_len) as usize {
              return Err(efi::Status::INVALID_PARAMETER);
            }
            string_len += 1;
          }
          // At this point we should have either exeeded the structure or be pointing at the last char in LockPolicy->Name.
          // We should check to make sure that the policy Name comes immediately after this charcter.
          if state_name_string.offset(string_len+1) as usize !=
              data_buffer.offset((*raw_var_policy_header).offset_to_name as isize) as usize {
            return Err(efi::Status::INVALID_PARAMETER);
          }
          LockPolicyType::LockOnVarState(VarStateLock {
            namespace: (*raw_var_state_header).namespace,
            value: (*raw_var_state_header).value,
            name: String::from_utf16_lossy(slice::from_raw_parts(state_name_string, string_len as usize)),
          })
        },
        _ => return Err(efi::Status::INVALID_PARAMETER)
      };
      // Make sure that OffsetToName is exactly sizeof(VARIABLE_POLICY_ENTRY) if not VarState.
      // TODO: Find a better way to do this.
      if let LockPolicyType::LockOnVarState(_) = new_policy.lock_policy_type {
      }
      else if (*raw_var_policy_header).offset_to_name != RAW_VARIABLE_POLICY_ENTRY_SIZE as u16 {
          return Err(efi::Status::INVALID_PARAMETER);
      }
      // Check to make sure that the name has a terminating character
      // before the end of the structure.
      // We've already checked that the name is within the bounds of the structure.
      if (*raw_var_policy_header).size != (*raw_var_policy_header).offset_to_name {
        let mut string_len: isize = 0;
        let name_string = (raw_var_policy_header as *const u8)
                            .offset((*raw_var_policy_header).offset_to_name as isize)
                            as *const u16;
        while *(name_string.offset(string_len)) != 0 {
          if entry_end <= name_string.offset(string_len) as usize {
            return Err(efi::Status::INVALID_PARAMETER);
          }
          string_len += 1;
        }
        // Finally, we should be pointed at the very last character in Name, so we should be right
        // up against the end of the structure.
        if name_string.offset(string_len+1) as usize != entry_end {
          return Err(efi::Status::INVALID_PARAMETER);
        }
        new_policy.name = Some(
          String::from_utf16_lossy(slice::from_raw_parts(name_string, string_len as usize))
          );
      }
    }
    if new_policy.is_valid() {
      Ok(new_policy)
    }
    else {
      Err(efi::Status::INVALID_PARAMETER)
    }
  }
pub fn from_raw ( raw_var_policy_header : * const RawVariablePolicyEntry ) -> Result < Self , efi :: Status > { if raw_var_policy_header . is_null ( ) { return Err ( efi :: Status :: INVALID_PARAMETER ) ; } let mut new_policy = VariablePolicyEntry { min_size : Self :: NO_MIN_SIZE , max_size : Self :: NO_MAX_SIZE , attr_must_have : Self :: NO_MUST_ATTR , attr_cant_have : Self :: NO_CANT_ATTR , lock_policy_type : LockPolicyType :: NoLock , namespace : efi :: Guid :: from_fields ( 0 , 0 , 0 , 0 , 0 , & [ 0 , 0 , 0 , 0 , 0 , 0 ] ) , name : None } ; // Validate the first few fields of the structure. // If the header looks valid, start grabbing fields. unsafe { // Sanitize some quick values. if ( * raw_var_policy_header ) . version != VariablePolicyEntry :: RAW_ENTRY_REVISION || ( ( * raw_var_policy_header ) . size as usize ) < RAW_VARIABLE_POLICY_ENTRY_SIZE || ( * raw_var_policy_header ) . size < ( * raw_var_policy_header ) . offset_to_name { return Err ( efi :: Status :: INVALID_PARAMETER ) ; } new_policy . min_size = ( * raw_var_policy_header ) . min_size ; new_policy . max_size = ( * raw_var_policy_header ) . max_size ; new_policy . attr_must_have = ( * raw_var_policy_header ) . attr_must_have ; new_policy . attr_cant_have = ( * raw_var_policy_header ) . attr_cant_have ; new_policy . namespace = ( * raw_var_policy_header ) . namespace ; let data_buffer = raw_var_policy_header as * const u8 ; let entry_end = data_buffer . offset ( ( * raw_var_policy_header ) . size as isize ) as usize ; // Check for the valid list of lock policies. new_policy . lock_policy_type = match ( * raw_var_policy_header ) . lock_policy_type { RawLockPolicyType :: NO_LOCK => LockPolicyType :: NoLock , RawLockPolicyType :: LOCK_NOW => LockPolicyType :: LockNow , RawLockPolicyType :: LOCK_ON_CREATE => LockPolicyType :: LockOnCreate , RawLockPolicyType :: LOCK_ON_VAR_STATE => { let raw_var_state_header = data_buffer . add ( RAW_VARIABLE_POLICY_ENTRY_SIZE ) as * const RawVarStateLock ; // If the policy type is VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE, make sure that the matching state variable Name // terminates before the OffsetToName for the matching policy variable Name. let mut string_len : isize = 0 ; let state_name_string = ( raw_var_state_header as * const u8 ) . add ( RAW_VAR_STATE_LOCK_SIZE ) as * const u16 ; while * ( state_name_string . offset ( string_len ) ) != 0 { if entry_end <= state_name_string . offset ( string_len ) as usize { return Err ( efi :: Status :: INVALID_PARAMETER ) ; } string_len += 1 ; } // At this point we should have either exeeded the structure or be pointing at the last char in LockPolicy->Name. // We should check to make sure that the policy Name comes immediately after this charcter. if state_name_string . offset ( string_len + 1 ) as usize != data_buffer . offset ( ( * raw_var_policy_header ) . offset_to_name as isize ) as usize { return Err ( efi :: Status :: INVALID_PARAMETER ) ; } LockPolicyType :: LockOnVarState ( VarStateLock { namespace : ( * raw_var_state_header ) . namespace , value : ( * raw_var_state_header ) . value , name : String :: from_utf16_lossy ( slice :: from_raw_parts ( state_name_string , string_len as usize ) ) , } ) } , _ => return Err ( efi :: Status :: INVALID_PARAMETER ) } ; // Make sure that OffsetToName is exactly sizeof(VARIABLE_POLICY_ENTRY) if not VarState. // TODO: Find a better way to do this. if let LockPolicyType :: LockOnVarState ( _ ) = new_policy . lock_policy_type { } else if ( * raw_var_policy_header ) . offset_to_name != RAW_VARIABLE_POLICY_ENTRY_SIZE as u16 { return Err ( efi :: Status :: INVALID_PARAMETER ) ; } // Check to make sure that the name has a terminating character // before the end of the structure. // We've already checked that the name is within the bounds of the structure. if ( * raw_var_policy_header ) . size != ( * raw_var_policy_header ) . offset_to_name { let mut string_len : isize = 0 ; let name_string = ( raw_var_policy_header as * const u8 ) . offset ( ( * raw_var_policy_header ) . offset_to_name as isize ) as * const u16 ; while * ( name_string . offset ( string_len ) ) != 0 { if entry_end <= name_string . offset ( string_len ) as usize { return Err ( efi :: Status :: INVALID_PARAMETER ) ; } string_len += 1 ; } // Finally, we should be pointed at the very last character in Name, so we should be right // up against the end of the structure. if name_string . offset ( string_len + 1 ) as usize != entry_end { return Err ( efi :: Status :: INVALID_PARAMETER ) ; } new_policy . name = Some ( String :: from_utf16_lossy ( slice :: from_raw_parts ( name_string , string_len as usize ) ) ) ; } } if new_policy . is_valid ( ) { Ok ( new_policy ) } else { Err ( efi :: Status :: INVALID_PARAMETER ) } }
TODO: Have this return specific error codes, rather than EFI codes.
TODO : Have this return specific error codes rather than EFI codes .
raw_var_policy_header
*const RawVariablePolicyEntry
raw_var_policy_header
*const RawVariablePolicyEntry