vfrservices.cpp

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

CPP
755
字号
          if (Curr->Next != NULL) {
            BytesLeftThisOpcode = (UINT32)Curr->Next->OpcodeByte;
          }
        }
        fprintf (OutFptr, "%02X ", (UINT32)Curr->OpcodeByte);
        ByteCount++;
        BytesLeftThisOpcode--;
        if (BytesLeftThisOpcode == 0) {
          fprintf (OutFptr, "\n");
        }
        Curr = Curr->Next;
      }
    }
    //
    // Dump any remaining lines from the input file
    //
    while (fgets (Line, sizeof (Line), InFptr) != NULL) {
      fprintf (OutFptr, "%s", Line);
    }
    fclose (InFptr);
    fclose (OutFptr);
  }
  //
  // Debug code to make sure that each opcode we write out has as many
  // bytes as the IFR structure requires. If there were errors, then
  // don't do this step.
  //
  if (GetUtilityStatus () != STATUS_ERROR) {
    Curr = mIfrBytes;
    ByteCount = 0;
    while (Curr != NULL) {
      //
      // First byte is the opcode, second byte is the length
      //
      if (Curr->Next == NULL) {
        Error (__FILE__, __LINE__, 0, "application error", "last opcode written does not contain a length byte");
        break;
      }
      Count = (UINT32)Curr->Next->OpcodeByte;
      if (Count == 0) {
        Error (
          __FILE__, 
          __LINE__, 
          0, 
          "application error", 
          "opcode with 0 length specified in output at offset 0x%X", 
          ByteCount
          );
        break;
      }
      //
      // Check the length
      //
      if ((Curr->OpcodeByte > EFI_IFR_LAST_OPCODE) || (Curr->OpcodeByte == 0)) {
        Error (
          __FILE__, 
          __LINE__, 
          0, 
          "application error", 
          "invalid opcode 0x%X in output at offset 0x%X", 
          (UINT32) Curr->OpcodeByte, ByteCount
          );
      } else if (mOpcodeSizes[Curr->OpcodeByte].Size < 0) {
        //
        // For those cases where the length is variable, the size is negative, and indicates
        // the miniumum size.
        //
        if ((mOpcodeSizes[Curr->OpcodeByte].Size * -1) > Count) {
          Error (
            __FILE__, 
            __LINE__, 
            0, 
            "application error", 
            "insufficient number of bytes written for %s at offset 0x%X",
            mOpcodeSizes[Curr->OpcodeByte].Name, 
            ByteCount
            );
        }
      } else {
        //
        // Check for gaps
        //
        if (mOpcodeSizes[Curr->OpcodeByte].Size == 0) {
          Error (
            __FILE__, 
            __LINE__, 
            0, 
            "application error", 
            "invalid opcode 0x%X in output at offset 0x%X", 
            (UINT32)Curr->OpcodeByte, 
            ByteCount
            );
        } else {
          //
          // Check size
          //
          if (mOpcodeSizes[Curr->OpcodeByte].Size != Count) {
            Error (
              __FILE__, 
              __LINE__, 
              0, 
              "application error", 
              "invalid number of bytes (%d written s/b %d) written for %s at offset 0x%X",
              Count, 
              mOpcodeSizes[Curr->OpcodeByte].Size, 
              mOpcodeSizes[Curr->OpcodeByte].Name, 
              ByteCount
              );
          }
        }
      }
      //
      // Skip to next opcode
      //
      while (Count > 0) {
        ByteCount++;
        if (Curr == NULL) {
          Error (__FILE__, __LINE__, 0, "application error", "last opcode written has invalid length");
          break;
        }
        Curr = Curr->Next;
        Count--;
      }
    }
  }
}

VfrOpcodeHandler::~VfrOpcodeHandler(
  ) 
/*++

Routine Description:
  Destructor for the VFR opcode handler. Free up memory allocated
  while parsing the VFR script.
  
Arguments:
  None

Returns:
  None

--*/
{
  IFR_BYTE    *Curr;
  IFR_BYTE    *Next;
  //
  // Free up the IFR bytes
  //
  Curr = mIfrBytes;
  while (Curr != NULL) {
    Next = Curr->Next;
    free (Curr);
    Curr = Next;
  }
}

int 
VfrOpcodeHandler::AddOpcodeByte (
  UINT8 OpcodeByte, 
  UINT32 LineNum
  ) 
/*++

Routine Description:
  This function is invoked by the parser when a new IFR
  opcode should be emitted.
  
Arguments:
  OpcodeByte  - the IFR opcode
  LineNum     - the line number from the source file that resulted
                in the opcode being emitted.

Returns:
  0 always

--*/
{
  UINT32 Count;

  FlushQueue();
  //
  // Now add this new byte
  //
  mQueuedOpcodeByte       = OpcodeByte;
  mQueuedLineNum          = LineNum;
  mQueuedOpcodeByteValid  = 1;
  return 0;
}

VOID 
VfrOpcodeHandler::AddByte (
  UINT8 ByteVal, 
  UINT8 KeyByte
  )
/*++

Routine Description:
  This function is invoked by the parser when it determines
  that more raw IFR bytes should be emitted to the output stream.
  Here we just queue them up into an output buffer.
  
Arguments:
  ByteVal   - the raw byte to emit to the output IFR stream
  KeyByte   - a value that can be used for debug. 

Returns:
  None

--*/
{
  //
  // Check for buffer overflow
  //
  if (mQueuedByteCount > MAX_QUEUE_COUNT) {
    Error (PROGRAM_NAME, 0, 0, NULL, "opcode queue overflow");
  } else {
    mQueuedBytes[mQueuedByteCount]    = ByteVal;
    mQueuedKeyBytes[mQueuedByteCount] = KeyByte;
    mQueuedByteCount++;
  }
}

int 
VfrOpcodeHandler::FlushQueue (
  )
/*++

Routine Description:
  This function is invoked to flush the internal IFR buffer.
  
Arguments:
  None

Returns:
  0 always

--*/
{
  UINT32 Count;
  UINT32 EmitNoneOnePair;

  EmitNoneOnePair = 0;
  //
  // If the secondary varstore was specified, then we have to emit
  // a varstore-select-pair opcode, which only applies to the following
  // statement. 
  //
  if (mSecondaryVarStoreIdSet) {
    mSecondaryVarStoreIdSet = 0;
    //
    // If primary and secondary are the same as the current default
    // varstore, then we don't have to do anything.
    // Note that the varstore-select-pair only applies to the following
    // opcode.
    //
    if ((mPrimaryVarStoreId != mSecondaryVarStoreId) || (mPrimaryVarStoreId != mDefaultVarStoreId)) {
      IAddByte (EFI_IFR_VARSTORE_SELECT_PAIR_OP, 'O', mQueuedLineNum);
      IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT_PAIR), 'L', 0);
      IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);
      IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);
      IAddByte ((UINT8)mSecondaryVarStoreId, 0, 0);
      IAddByte ((UINT8)(mSecondaryVarStoreId >> 8), 0, 0);
    }
  } else if (mPrimaryVarStoreIdSet != 0) {
    mPrimaryVarStoreIdSet = 0;
    if (mDefaultVarStoreId != mPrimaryVarStoreId) {
      //
      // The VFR statement referenced a different variable store 
      // than the last one we reported. Insert a new varstore select 
      // statement. 
      //
      IAddByte (EFI_IFR_VARSTORE_SELECT_OP, 'O', mQueuedLineNum);
      IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT), 'L', 0);
      IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);
      IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);
      mDefaultVarStoreId = mPrimaryVarStoreId;
    }
  }
  //
  // Likely a new opcode is being added. Since each opcode item in the IFR has 
  // a header that specifies the size of the opcode item (which we don't
  // know until we find the next opcode in the VFR), we queue up bytes
  // until we know the size. Then we write them out. So flush the queue
  // now.
  //
  if (mQueuedOpcodeByteValid != 0) {
    // 
    // Add the previous opcode byte, the length byte, and the binary
    // data.
    //
    IAddByte (mQueuedOpcodeByte, 'O', mQueuedLineNum);
    IAddByte ((UINT8)(mQueuedByteCount + 2), 'L', 0);
    for (Count = 0; Count < mQueuedByteCount; Count++) {
      IAddByte (mQueuedBytes[Count], mQueuedKeyBytes[Count], 0);          
    }
    mQueuedByteCount = 0;
    mQueuedOpcodeByteValid = 0;
  }    
  return 0;
}

int 
VfrOpcodeHandler::IAddByte (
  UINT8   ByteVal, 
  UINT8   KeyByte, 
  UINT32  LineNum
  )
/*++

Routine Description:
  This internal function is used to add actual IFR bytes to
  the output stream. Most other functions queue up the bytes
  in an internal buffer. Once they come here, there's no
  going back.

  
Arguments:
  ByteVal   - value to write to output 
  KeyByte   - key value tied to the byte -- useful for debug
  LineNum   - line number from source file the byte resulted from

Returns:
  0 - if successful
  1 - failed due to memory allocation failure

--*/
{
  IFR_BYTE    *NewByte;
  NewByte = (IFR_BYTE *)malloc (sizeof (IFR_BYTE));
  if (NewByte == NULL) {
    return 1;
  }
  memset ((char *)NewByte, 0, sizeof (IFR_BYTE));
  NewByte->OpcodeByte = ByteVal;
  NewByte->KeyByte = KeyByte;
  NewByte->LineNum = LineNum;
  //
  // Add to the list
  //
  if (mIfrBytes == NULL) {
    mIfrBytes = NewByte;
  } else {
    mLastIfrByte->Next = NewByte;
  } 
  mLastIfrByte = NewByte;
  mBytesWritten++;
  return 0;
}

VOID 
WriteStandardFileHeader (
  FILE *OutFptr
  ) 
/*++

Routine Description:
  This function is invoked to emit a standard header to an
  output text file.
  
Arguments:
  OutFptr - file to write the header to

Returns:
  None

--*/
{
  UINT32 TempIndex;
  for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) {
    fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]);
  }
  //
  // Write out the VFR compiler version
  //
  fprintf (OutFptr, "//  VFR compiler version " VFR_COMPILER_VERSION "\n//\n");
}

⌨️ 快捷键说明

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