strings.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,275 行 · 第 1/3 页

C
1,275
字号
    // Notice that if the string was being added as a new token, we don't have to worry about the
    // offsets changing in the other indexes
    //
    EfiCopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), &StringPointer[Index], sizeof (RELOFST));
    Count = Count + sizeof (RELOFST);
    StringCount++;
  }
  //
  // If we are adding a new string the above for loop did not copy the offset for us
  //
  if (AddString) {
    //
    // Since the Index is pointing to the beginning of the first string, we need to gather the size of the previous
    // offset's string and create an offset to our new string.
    //
    EfiCopyMem (&Offset, &StringPointer[Index - 1], sizeof (RELOFST));
    StringLocation  = (CHAR8 *) StringPack;
    StringLocation  = StringLocation + Offset - sizeof (RELOFST);

    //
    // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues
    //
    for (Length = 0;
         (StringLocation[Length] != 0) || (StringLocation[Length + 1] != 0);
         Length = (RELOFST) (Length + 2)
        )
      ;
    Length      = (RELOFST) (Length + 2);

    StringSize  = (RELOFST) (Offset + Length);

    //
    // Copy the new string offset
    //
    EfiCopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), &StringSize, sizeof (RELOFST));
    Count = Count + sizeof (RELOFST);

    EfiCopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
    Length = Length + sizeof (RELOFST);
    EfiCopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32));
  }
  //
  // Set Location to the First String
  //
  if (ResetStrings) {
    Index = OriginalStringCount;
  }
  //
  // Set Location to the First String
  //
  Location  = (UINT8 *) &StringPointer[Index];
  Index     = 0;

  //
  // Keep copying strings until you run into two CHAR16's in a row that are NULL
  //
  do {
    if ((*Reference == Increment) && !AddString) {
      StringLocation = ((CHAR8 *) (&NewBuffer->IfrData) + Count);
      EfiCopyMem (StringLocation, NewString, EfiStrSize (NewString));

      //
      // Advance the destination location by Count number of bytes
      //
      Count = Count + EfiStrSize (NewString);

      //
      // Add the difference between the new string and the old string to the length
      //
      EfiCopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));

      //
      // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues
      //
      StringLocation = (UINT8 *) &Location[Index];
      for (Offset = 0;
           (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0);
           Offset = (RELOFST) (Offset + 2)
          )
        ;
      Offset  = (RELOFST) (Offset + 2);

      Length  = Length + (UINT32) EfiStrSize (NewString) - Offset;

      EfiCopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32));
    } else {
      StringLocation = (UINT8 *) &Location[Index];
      for (Offset = 0;
           (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0);
           Offset = (RELOFST) (Offset + 2)
          )
        ;
      Offset = (RELOFST) (Offset + 2);

      EfiCopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringLocation, Offset);

      //
      // Advance the destination location by Count number of bytes
      //
      Count = Count + Offset;
    }
    //
    // Retrieve the number of characters to advance the index - should land at beginning of next string
    //
    Index = Index + Offset;
    Increment++;
    StringCount--;
    Offset = 0;
  } while (StringCount > 0);

  //
  // If we are adding a new string, then the above do/while will not suffice
  //
  if (AddString) {
    Offset = (RELOFST) EfiStrSize (NewString);
    EfiCopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), NewString, Offset);

    Count = Count + EfiStrSize (NewString);
    EfiCopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
    Length = Length + (UINT32) EfiStrSize (NewString);
    EfiCopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32));
  }

  if (ResetStrings) {
    //
    // Skip the remainder of strings in the string package
    //
    StringCount = OriginalStringCount - TotalStringCount;

    while (StringCount > 0) {
      StringLocation = (UINT8 *) &Location[Index];
      for (Offset = 0;
           (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0);
           Offset = (RELOFST) (Offset + 2)
          )
        ;
      Offset  = (RELOFST) (Offset + 2);
      Index   = Index + Offset;
      StringCount--;

      //
      // Adjust the size of the string pack by the string size we just skipped.
      // Also reduce the length by the size of a RelativeOffset value since we
      // obviously would have skipped that as well.
      //
      EfiCopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
      Length = Length - Offset - sizeof (RELOFST);
      EfiCopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32));
    }
  }

  StringPack = (EFI_HII_STRING_PACK *) &Location[Index];

  EfiCopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
  for (; Length != 0;) {

    EfiCopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, Length);

    Count       = Count + Length;
    StringPack  = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length);
    EfiCopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
  }
  //
  // Copy the null terminator to the new buffer
  //
  EfiCopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, sizeof (EFI_HII_STRING_PACK));

  //
  // Based on if there is IFR data in this package instance, determine
  // what the location is of the beginning of the string data.
  //
  if (StringPackageInstance->IfrSize > 0) {
    Location      = (CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize;
    StringPack    = (EFI_HII_STRING_PACK *) Location;
    Location      = (CHAR8 *) (&NewBuffer->IfrData) + NewBuffer->IfrSize;
    NewStringPack = (EFI_HII_STRING_PACK *) Location;
  } else {
    StringPack    = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData);
    NewStringPack = (EFI_HII_STRING_PACK *) (&NewBuffer->IfrData);
  }

  EfiCopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
  for (; Length != 0;) {
    //
    // Since we updated the old version of the string data as we moved things over
    // And we had a chicken-egg problem with the data we copied, let's post-fix the new
    // buffer with accurate length data.
    //
    EfiCopyMem (&Count, &NewStringPack->Header.Length, sizeof (UINT32));
    EfiCopyMem (&NewStringPack->Header.Length, &StringPack->Header.Length, sizeof (UINT32));
    EfiCopyMem (&StringPack->Header.Length, &Count, sizeof (UINT32));

    EfiCopyMem (&Count, &NewStringPack->Header.Length, sizeof (UINT32));
    NewStringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (NewStringPack) + Count);
    EfiCopyMem (&Count, &StringPack->Header.Length, sizeof (UINT32));
    StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Count);
    EfiCopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
  }

  GetPackSize ((VOID *) ((CHAR8 *) (&NewBuffer->IfrData) + NewBuffer->IfrSize), &NewBuffer->StringSize, NULL);

  //
  // Search through the handles until the requested handle is found.
  //
  for (HandleDatabase = HiiData->DatabaseHead;
       HandleDatabase->Handle != 0;
       HandleDatabase = HandleDatabase->NextHandleDatabase
      ) {
    if (HandleDatabase->Handle == StringPackageInstance->Handle) {
      //
      // Free the previous buffer associated with this handle, and assign the new buffer to the handle
      //
      gBS->FreePool (HandleDatabase->Buffer);
      HandleDatabase->Buffer = NewBuffer;
      break;
    }
  }

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
HiiNewString (
  IN     EFI_HII_PROTOCOL       *This,
  IN     CHAR16                 *Language,
  IN     EFI_HII_HANDLE         Handle,
  IN OUT STRING_REF             *Reference,
  IN     CHAR16                 *NewString
  )
/*++

Routine Description:
  This function allows a new String to be added to an already existing String Package.
  We will make a buffer the size of the package + EfiStrSize of the new string.  We will
  copy the string package that first gets changed and the following language packages until
  we encounter the NULL string package.  All this time we will ensure that the offsets have
  been adjusted.  

Arguments:
  
Returns: 

--*/
{
  UINTN       Index;
  CHAR16      *LangCodes;
  CHAR16      Lang[4];
  STRING_REF  OriginalValue;
  EFI_STATUS  Status;

  //
  // To avoid a warning 4 uninitialized variable warning
  //
  Status = EFI_SUCCESS;

  Status = HiiGetPrimaryLanguages (
            This,
            Handle,
            &LangCodes
            );

  if (!EFI_ERROR (Status)) {
    OriginalValue = *Reference;

    if (Language == NULL) {
      for (Index = 0; LangCodes[Index] != 0; Index += 3) {
        *Reference = OriginalValue;
        EfiCopyMem (Lang, &LangCodes[Index], 6);
        Lang[3] = 0;
        Status = HiiNewString2 (
                  This,
                  Lang,
                  Handle,
                  Reference,
                  NewString,
                  FALSE
                  );

      }
    } else {
      Status = HiiNewString2 (
                This,
                Language,
                Handle,
                Reference,
                NewString,
                FALSE
                );
    }

    gBS->FreePool (LangCodes);
  }

  return Status;
}

EFI_STATUS
EFIAPI
HiiResetStrings (
  IN     EFI_HII_PROTOCOL   *This,
  IN     EFI_HII_HANDLE     Handle
  )
/*++

Routine Description:
  
    This function removes any new strings that were added after the initial string export for this handle.

Arguments:

Returns: 

--*/
{
  UINTN       Index;
  CHAR16      *LangCodes;
  CHAR16      Lang[4];
  STRING_REF  Reference;
  CHAR16      NewString;
  EFI_STATUS  Status;

  Reference = 1;
  NewString = 0;

  HiiGetPrimaryLanguages (
    This,
    Handle,
    &LangCodes
    );

  for (Index = 0; LangCodes[Index] != 0; Index += 3) {
    EfiCopyMem (Lang, &LangCodes[Index], 6);
    Lang[3] = 0;
    Status = HiiNewString2 (
              This,
              Lang,
              Handle,
              &Reference,
              &NewString,
              TRUE
              );

  }

  gBS->FreePool (LangCodes);
  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
HiiGetString (
  IN     EFI_HII_PROTOCOL   *This,
  IN     EFI_HII_HANDLE     Handle,
  IN     STRING_REF         Token,
  IN     BOOLEAN            Raw,
  IN     CHAR16             *LanguageString,
  IN OUT UINTN              *BufferLength,
  OUT    EFI_STRING         StringBuffer
  )
/*++

Routine Description:
  
  This function extracts a string from a package already registered with the EFI HII database.

Arguments:
  This            - A pointer to the EFI_HII_PROTOCOL instance.
  Handle          - The HII handle on which the string resides.
  Token           - The string token assigned to the string.
  Raw             - If TRUE, the string is returned unedited in the internal storage format described
                    above. If false, the string returned is edited by replacing <cr> with <space> 
                    and by removing special characters such as the <wide> prefix.
  LanguageString  - Pointer to a NULL-terminated string containing a single ISO 639-2 language
                    identifier, indicating the language to print. If the LanguageString is empty (starts
                    with a NULL), the default system language will be used to determine the language.
  BufferLength    - Length of the StringBuffer. If the status reports that the buffer width is too
                    small, this parameter is filled with the length of the buffer needed.
  StringBuffer    - The buffer designed to receive the characters in the string. Type EFI_STRING is
                    defined in String.

Returns: 
  EFI_INVALID_PARAMETER - If input parameter is invalid.
  EFI_BUFFER_TOO_SMALL  - If the *BufferLength is too small.
  EFI_SUCCESS           - Operation is successful.
  
--*/
{
  EFI_HII_PACKAGE_INSTANCE  *PackageInstance;
  EFI_HII_PACKAGE_INSTANCE  *StringPackageInstance;
  EFI_HII_DATA              *HiiData;
  EFI_HII_HANDLE_DATABASE   *HandleDatabase;
  EFI_HII_STRING_PACK       *StringPack;
  RELOFST                   *StringPointer;
  EFI_STATUS                Status;
  UINTN                     DataSize;
  CHAR8                     Lang[3];
  CHAR16                    Language[3];
  UINT32                    Length;
  UINTN                     Count;
  RELOFST                   Offset;
  CHAR16                    *Local;
  UINT16                    Zero;
  UINT16                    Narrow;
  UINT16                    Wide;
  UINT16                    NoBreak;
  BOOLEAN                   LangFound;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  LangFound       = TRUE;

  DataSize        = sizeof (Lang);

  HiiData         = EFI_HII_DATA_FROM_THIS (This);

  PackageInstance = NULL;
  Zero            = 0;
  Narrow          = NARROW_CHAR;
  Wide            = WIDE_CHAR;
  NoBreak         = NON_BREAKING_CHAR;

  //

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?