processoptions.c

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

C
1,634
字号
    if (Selected) {
      StringPtr = EfiLibAllocateZeroPool (Tag->Maximum);
      ASSERT (StringPtr);

      Status = ReadString (MenuOption, StringPtr);

      if (!EFI_ERROR (Status)) {
        EfiCopyMem (gPreviousValue, NvRamMap, MenuOption->ThisTag->StorageWidth);
        EfiCopyMem (&VariableDefinition->NvRamMap[Tag->StorageStart], StringPtr, Tag->StorageWidth);

        UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE);
      }

      gBS->FreePool (StringPtr);
      return Status;
    } else {
      for (Index = 0; Index < gOptionBlockWidth; Index++) {
        if (VariableDefinition->NvRamMap[Tag->StorageStart + (Index * 2)] != 0x0000) {
          EfiCopyMem (OptionString[0] + Index, &VariableDefinition->NvRamMap[Tag->StorageStart + (Index * 2)], 2);
        } else {
          if (Index == 0) {
            *(OptionString[0] + Index)      = '_';
            *(OptionString[0] + 1 + Index)  = 0;
          }
          break;
        }
      }

      return Status;
    }

  case EFI_IFR_PASSWORD_OP:
    //
    // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
    // created entry which has an expanded NvMap requirement.  We won't save this information - but we need to adjust
    // the NvMap so that we can properly display the information
    //
    if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {
      AdjustNvMap (FileFormTags, MenuOption);
      NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];
    }

    if (Selected) {
      StringPtr = EfiLibAllocateZeroPool (Tag->Maximum);
      ASSERT (StringPtr);

      //
      // If interactive, read the password and do the appropriate callbacks in that routine.
      // Since interactive passwords assume to handle the password data in a separate variable
      // storage, we don't need to do more than what is below for password callbacks
      //
      if (Tag->Flags & EFI_IFR_FLAG_INTERACTIVE) {
        MenuOption->Tags[0].CallbackHandle  = FileFormTags->FormTags.Tags[0].CallbackHandle;
        Status = ReadPassword (MenuOption, TRUE, Tag, PageData, FALSE, FileFormTags, StringPtr);
        EfiZeroMem (StringPtr, Tag->Maximum);

        if (EFI_ERROR (Status)) {
          if (Status == EFI_NOT_READY) {
            gBS->FreePool (StringPtr);
            return EFI_SUCCESS;
          }
        }

        Status = ReadPassword (MenuOption, TRUE, Tag, PageData, TRUE, FileFormTags, StringPtr);
        gBS->FreePool (StringPtr);
        return EFI_SUCCESS;
      }

      for (Index = 0; Index < Tag->Maximum; Index++) {
        if (VariableDefinition->NvRamMap[Tag->StorageStart + Index] != 0x00) {
          //
          // There is something there!  Prompt for password
          //
          Status = ReadPassword (MenuOption, TRUE, Tag, PageData, FALSE, FileFormTags, StringPtr);
          if (EFI_ERROR (Status)) {
            gBS->FreePool (StringPtr);
            return EFI_SUCCESS;
          }

          if (Tag->Encoding == 1) {
            EncodePassword (StringPtr, (UINT8) Tag->Maximum);
            Status = EfiCompareMem (StringPtr, &VariableDefinition->NvRamMap[Tag->StorageStart], Tag->Maximum);
          } else {
            Status = EfiCompareMem (StringPtr, &VariableDefinition->NvRamMap[Tag->StorageStart], Tag->Maximum);
          }

          if (Status != 0) {
            gBS->FreePool (StringPtr);
            return EFI_SUCCESS;
          } else {
            break;
          }
        }
      }
      //
      // Clean the string
      //
      EfiZeroMem (StringPtr, Tag->Maximum);

      //
      // No password set!  Go ahead and prompt the user for a password.
      //
      Status = ReadPassword (MenuOption, FALSE, Tag, PageData, FALSE, FileFormTags, StringPtr);

      if (EFI_ERROR (Status)) {
        //
        // User couldn't figure out how to type two identical passwords
        //
        gBS->FreePool (StringPtr);
        return EFI_SUCCESS;
      }
      //
      // Very simple example of how one MIGHT do password encoding
      //
      if (Tag->Encoding == 1) {
        EncodePassword (StringPtr, (UINT8) Tag->Maximum);
      }

      TmpNvRamMap = EfiLibAllocatePool (VariableDefinition->VariableSize);
      ASSERT (TmpNvRamMap != NULL);

      Count = VariableDefinition->VariableSize;

      if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
        Status = FormCallback->NvRead (
                                FormCallback,
                                VariableDefinition->VariableName,
                                &VariableDefinition->Guid,
                                NULL,
                                &Count,
                                (VOID *) TmpNvRamMap
                                );
      } else {
        Status = gRT->GetVariable (
                        VariableDefinition->VariableName,
                        &VariableDefinition->Guid,
                        NULL,
                        &Count,
                        (VOID *) TmpNvRamMap
                        );
      }

      EfiCopyMem (&VariableDefinition->NvRamMap[Tag->StorageStart], StringPtr, Tag->StorageWidth);
      EfiCopyMem (&TmpNvRamMap[Tag->StorageStart], StringPtr, Tag->StorageWidth);

      if ((FormCallback != NULL) && (FormCallback->NvWrite != NULL)) {
        Status = FormCallback->NvWrite (
                                FormCallback,
                                VariableDefinition->VariableName,
                                &VariableDefinition->Guid,
                                EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                                VariableDefinition->VariableSize,
                                (VOID *) TmpNvRamMap,
                                &gResetRequired
                                );
      } else {
        Status = gRT->SetVariable (
                        VariableDefinition->VariableName,
                        &VariableDefinition->Guid,
                        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                        VariableDefinition->VariableSize,
                        (VOID *) TmpNvRamMap
                        );
      }

      gBS->FreePool (TmpNvRamMap);
      gBS->FreePool (StringPtr);
      break;
    }

  default:
    break;
  }

  return EFI_SUCCESS;
}

VOID
ProcessHelpString (
  IN  CHAR16                      *StringPtr,
  OUT CHAR16                      **FormattedString,
  IN  UINTN                       RowCount
  )
{
  UINTN CurrIndex;
  UINTN PrevIndex;
  UINTN SearchIndex;
  UINTN PrevSearchIndex;
  UINTN StringCount;
  UINTN PageCount;

  StringCount = 0;
  PrevIndex   = 0;
  CurrIndex   = gHelpBlockWidth - 1;

  if (*FormattedString != NULL) {
    gBS->FreePool (*FormattedString);
    *FormattedString = NULL;
  }

  for (; CurrIndex > PrevIndex; CurrIndex--) {
    //
    // In the case where the string ended and a new one is immediately after it
    // we need to check for the null-terminator and reset the CurrIndex
    //
    SearchIndex     = CurrIndex;
    PrevSearchIndex = PrevIndex;

    for (; SearchIndex > PrevSearchIndex; PrevSearchIndex++) {
      if ((StringPtr[PrevSearchIndex] == CHAR_NULL) || (StringPtr[PrevSearchIndex] == CHAR_LINEFEED)) {
        CurrIndex = PrevSearchIndex;
        break;
      }

      if (StringPtr[PrevSearchIndex] == CHAR_CARRIAGE_RETURN) {
        if (StringPtr[PrevSearchIndex + 1] == CHAR_LINEFEED) {
          //
          // Found a "\n",advance to the next new line.
          //
          CurrIndex = PrevSearchIndex + 1;
          break;
        } else {
          //
          // Found a "\r",return to the start of the current line.
          //
          PrevIndex = PrevSearchIndex + 1;
          CurrIndex = PrevSearchIndex + gHelpBlockWidth;
          continue;
        }
      }
    }

    //
    // End of the string, thus stop counting.
    //
    if (StringPtr[CurrIndex] == CHAR_NULL) {
      StringCount++;
      break;
    }
    //
    // The premise is that for every HELP_BLOCK_WIDTH we rewind
    // until we find the first space.  That is the delimiter for
    // the string, and we will then advance our CurrIndex another
    // HELP_BLOCK_WIDTH and continue the process breaking the larger
    // string into chunks that fit within the HELP_BLOCK_WIDTH requirements.
    //
    if (StringPtr[CurrIndex] == CHAR_SPACE) {
      //
      // How many strings have been found?
      //
      StringCount++;
      PrevIndex = CurrIndex + 1;
      CurrIndex = CurrIndex + gHelpBlockWidth;
    }
    //
    // Found a Linefeed, advance to the next line.
    //
    if (StringPtr[CurrIndex] == CHAR_LINEFEED) {
      StringCount++;
      PrevIndex = CurrIndex + 1;
      CurrIndex = CurrIndex + gHelpBlockWidth;
    }
  }
  //
  // endfor
  //
  // Round the value up one (doesn't hurt)
  //
  StringCount++;

  //
  // Determine the number of pages this help string occupies
  //
  PageCount = StringCount / RowCount;
  if (StringCount % RowCount > 0) {
    PageCount++;
  }
  //
  // Convert the PageCount into lines so we can allocate the correct buffer size
  //
  StringCount = PageCount * RowCount;

  //
  // We now know how many strings we will have, so we can allocate the
  // space required for the array or strings.
  //
  *FormattedString = EfiLibAllocateZeroPool ((StringCount) * (gHelpBlockWidth + 1) * 2);
  ASSERT (*FormattedString);

  StringCount = 0;
  PrevIndex   = 0;
  CurrIndex   = gHelpBlockWidth - 1;

  for (; CurrIndex > PrevIndex; CurrIndex--) {
    //
    // In the case where the string ended and a new one is immediately after it
    // we need to check for the null-terminator and reset the CurrIndex
    //
    SearchIndex     = CurrIndex;
    PrevSearchIndex = PrevIndex;

    for (; SearchIndex > PrevSearchIndex; PrevSearchIndex++) {
      if ((StringPtr[PrevSearchIndex] == CHAR_NULL) || (StringPtr[PrevSearchIndex] == CHAR_LINEFEED)) {
        CurrIndex = PrevSearchIndex;
        break;
      }

      if (StringPtr[PrevSearchIndex] == CHAR_CARRIAGE_RETURN) {
        if (StringPtr[PrevSearchIndex + 1] == CHAR_LINEFEED) {
          //
          // Found a "\n",advance to the next new line.
          //
          CurrIndex = PrevSearchIndex + 1;
          break;
        } else {
          //
          // Found a "\r",return to the start of the current line.
          //
          PrevIndex = PrevSearchIndex + 1;
          CurrIndex = PrevSearchIndex + gHelpBlockWidth;
          continue;
        }
      }
    }

    //
    // End of the string, thus stop counting.

⌨️ 快捷键说明

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