bbssupport.c

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

C
1,604
字号
  Ptr += sizeof (BBS_TYPE);
  NewPtr += sizeof (BBS_TYPE);
  Length                = *((UINT16 *) Ptr);
  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
  Ptr += sizeof (UINT16);

  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
        LocalBbsTable[*Ptr].DeviceType != BBS_FLOPPY
        ) {
      Ptr += sizeof (UINT16);
      continue;
    }

    NewFDPtr[FDIndex] = *(UINT16 *) Ptr;
    FDIndex++;
    Ptr += sizeof (UINT16);
  }
  //
  // copy HD
  //
  NewPtr                  = (UINT8 *) NewHDPtr - HeaderSize;
  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);
  Ptr += sizeof (BBS_TYPE);
  NewPtr += sizeof (BBS_TYPE);
  Length                = *((UINT16 *) Ptr);
  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
  Ptr += sizeof (UINT16);

  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
        LocalBbsTable[*Ptr].DeviceType != BBS_HARDDISK
        ) {
      Ptr += sizeof (UINT16);
      continue;
    }

    NewHDPtr[HDIndex] = *(UINT16 *) Ptr;
    HDIndex++;
    Ptr += sizeof (UINT16);
  }
  //
  // copy CD
  //
  NewPtr                  = (UINT8 *) NewCDPtr - HeaderSize;
  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);
  Ptr += sizeof (BBS_TYPE);
  NewPtr += sizeof (BBS_TYPE);
  Length                = *((UINT16 *) Ptr);
  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
  Ptr += sizeof (UINT16);

  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
        LocalBbsTable[*Ptr].DeviceType != BBS_CDROM
        ) {
      Ptr += sizeof (UINT16);
      continue;
    }

    NewCDPtr[CDIndex] = *(UINT16 *) Ptr;
    CDIndex++;
    Ptr += sizeof (UINT16);
  }
  //
  // copy NET
  //
  NewPtr                  = (UINT8 *) NewNETPtr - HeaderSize;
  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);
  Ptr += sizeof (BBS_TYPE);
  NewPtr += sizeof (BBS_TYPE);
  Length                = *((UINT16 *) Ptr);
  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
  Ptr += sizeof (UINT16);

  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
        LocalBbsTable[*Ptr].DeviceType != BBS_EMBED_NETWORK
        ) {
      Ptr += sizeof (UINT16);
      continue;
    }

    NewNETPtr[NETIndex] = *(UINT16 *) Ptr;
    NETIndex++;
    Ptr += sizeof (UINT16);
  }
  //
  // copy BEV
  //
  NewPtr                  = (UINT8 *) NewBEVPtr - HeaderSize;
  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);
  Ptr += sizeof (BBS_TYPE);
  NewPtr += sizeof (BBS_TYPE);
  Length                = *((UINT16 *) Ptr);
  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
  Ptr += sizeof (UINT16);

  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
        LocalBbsTable[*Ptr].DeviceType != BBS_BEV_DEVICE
        ) {
      Ptr += sizeof (UINT16);
      continue;
    }

    NewBEVPtr[BEVIndex] = *(UINT16 *) Ptr;
    BEVIndex++;
    Ptr += sizeof (UINT16);
  }

  for (Index = 0; Index < BbsCount; Index++) {
    if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
        (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM) ||
        (LocalBbsTable[Index].BootPriority == BBS_LOWEST_PRIORITY)
        ) {
      continue;
    }

    switch (LocalBbsTable[Index].DeviceType) {
    case BBS_FLOPPY:
      Idx       = &FDIndex;
      NewDevPtr = NewFDPtr;
      break;

    case BBS_HARDDISK:
      Idx       = &HDIndex;
      NewDevPtr = NewHDPtr;
      break;

    case BBS_CDROM:
      Idx       = &CDIndex;
      NewDevPtr = NewCDPtr;
      break;

    case BBS_EMBED_NETWORK:
      Idx       = &NETIndex;
      NewDevPtr = NewNETPtr;
      break;

    case BBS_BEV_DEVICE:
      Idx       = &BEVIndex;
      NewDevPtr = NewBEVPtr;
      break;

    default:
      Idx = NULL;
      break;
    }
    //
    // at this point we have copied those valid indexes to new buffer
    // and we should check if there is any new appeared boot device
    //
    if (Idx) {
      for (Index2 = 0; Index2 < *Idx; Index2++) {
        if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {
          break;
        }
      }

      if (Index2 == *Idx) {
        //
        // Index2 == *Idx means we didn't find Index
        // so Index is a new appeared device's index in BBS table
        // save it.
        //
        NewDevPtr[*Idx] = (UINT16) (Index & 0xFF);
        (*Idx)++;
      }
    }
  }

  if (FDCount) {
    //
    // Just to make sure that disabled indexes are all at the end of the array
    //
    for (Index = 0; Index < FDIndex - 1; Index++) {
      if (0xFF00 != (NewFDPtr[Index] & 0xFF00)) {
        continue;
      }

      for (Index2 = Index + 1; Index2 < FDIndex; Index2++) {
        if (0 == (NewFDPtr[Index2] & 0xFF00)) {
          tmp               = NewFDPtr[Index];
          NewFDPtr[Index]   = NewFDPtr[Index2];
          NewFDPtr[Index2]  = tmp;
          break;
        }
      }
    }
  }

  if (HDCount) {
    //
    // Just to make sure that disabled indexes are all at the end of the array
    //
    for (Index = 0; Index < HDIndex - 1; Index++) {
      if (0xFF00 != (NewHDPtr[Index] & 0xFF00)) {
        continue;
      }

      for (Index2 = Index + 1; Index2 < HDIndex; Index2++) {
        if (0 == (NewHDPtr[Index2] & 0xFF00)) {
          tmp               = NewHDPtr[Index];
          NewHDPtr[Index]   = NewHDPtr[Index2];
          NewHDPtr[Index2]  = tmp;
          break;
        }
      }
    }
  }

  if (CDCount) {
    //
    // Just to make sure that disabled indexes are all at the end of the array
    //
    for (Index = 0; Index < CDIndex - 1; Index++) {
      if (0xFF00 != (NewCDPtr[Index] & 0xFF00)) {
        continue;
      }

      for (Index2 = Index + 1; Index2 < CDIndex; Index2++) {
        if (0 == (NewCDPtr[Index2] & 0xFF00)) {
          tmp               = NewCDPtr[Index];
          NewCDPtr[Index]   = NewCDPtr[Index2];
          NewCDPtr[Index2]  = tmp;
          break;
        }
      }
    }
  }

  if (NETCount) {
    //
    // Just to make sure that disabled indexes are all at the end of the array
    //
    for (Index = 0; Index < NETIndex - 1; Index++) {
      if (0xFF00 != (NewNETPtr[Index] & 0xFF00)) {
        continue;
      }

      for (Index2 = Index + 1; Index2 < NETIndex; Index2++) {
        if (0 == (NewNETPtr[Index2] & 0xFF00)) {
          tmp               = NewNETPtr[Index];
          NewNETPtr[Index]  = NewNETPtr[Index2];
          NewNETPtr[Index2] = tmp;
          break;
        }
      }
    }
  }

  if (BEVCount) {
    //
    // Just to make sure that disabled indexes are all at the end of the array
    //
    for (Index = 0; Index < BEVIndex - 1; Index++) {
      if (0xFF00 != (NewBEVPtr[Index] & 0xFF00)) {
        continue;
      }

      for (Index2 = Index + 1; Index2 < BEVIndex; Index2++) {
        if (0 == (NewBEVPtr[Index2] & 0xFF00)) {
          tmp               = NewBEVPtr[Index];
          NewBEVPtr[Index]  = NewBEVPtr[Index2];
          NewBEVPtr[Index2] = tmp;
          break;
        }
      }
    }
  }

  SafeFreePool (DevOrder);

  Status = gRT->SetVariable (
                  VarLegacyDevOrder,
                  &EfiLegacyDevOrderGuid,
                  VAR_FLAG,
                  TotalSize,
                  NewDevOrder
                  );
  SafeFreePool (NewDevOrder);

  return Status;
}

EFI_STATUS
BdsSetBootPriority4SameTypeDev (
  IN UINT16                                              DeviceType,
  IN OUT BBS_TABLE                                       *LocalBbsTable,
  IN OUT UINT16                                          *Priority
  )
/*++
DeviceType           - BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM and so on
LocalBbsTable       - BBS table instance
Priority                 - As input arg, it is the start point of boot priority, as output arg, it is the start point of boot
                              priority can be used next time.
--*/
{
  UINT8   *DevOrder;

  UINT8   *OrigBuffer;
  UINT16  *DevIndex;
  UINTN   DevOrderSize;
  UINTN   DevCount;
  UINTN   Index;

  DevOrder = BdsLibGetVariableAndSize (
              VarLegacyDevOrder,
              &EfiLegacyDevOrderGuid,
              &DevOrderSize
              );
  if (NULL == DevOrder) {
    return EFI_OUT_OF_RESOURCES;
  }

  OrigBuffer = DevOrder;
  while (DevOrder < OrigBuffer + DevOrderSize) {
    if (DeviceType == * (BBS_TYPE *) DevOrder) {
      break;
    }

    DevOrder += sizeof (BBS_TYPE);
    DevOrder += *(UINT16 *) DevOrder;
  }

  if (DevOrder >= OrigBuffer + DevOrderSize) {
    SafeFreePool (OrigBuffer);
    return EFI_NOT_FOUND;
  }

  DevOrder += sizeof (BBS_TYPE);
  DevCount  = (*((UINT16 *) DevOrder) - sizeof (UINT16)) / sizeof (UINT16);
  DevIndex  = (UINT16 *) (DevOrder + sizeof (UINT16));
  //
  // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
  //
  for (Index = 0; Index < DevCount; Index++) {
    if ((DevIndex[Index] & 0xFF00) == 0xFF00) {
      //
      // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
      //
    } else {
      LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = *Priority;
      (*Priority)++;
    }
  }

  SafeFreePool (OrigBuffer);
  return EFI_SUCCESS;
}

VOID
PrintBbsTable (
  IN BBS_TABLE                      *LocalBbsTable
  )
{
  UINT16  Idx;

  DEBUG ((EFI_D_ERROR, "\n"));
  DEBUG ((EFI_D_ERROR, " NO  Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
  DEBUG ((EFI_D_ERROR, "=============================================\n"));
  for (Idx = 0; Idx < MAX_BBS_ENTRIES; Idx++) {
    if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) ||
        (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) ||
        (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY)
        ) {
      continue;
    }

    DEBUG (
      (EFI_D_ERROR,
      " %02x: %04x %02x/%02x/%02x %02x/02%x %04x %04x %04x:%04x\n",
      (UINTN) Idx,
      (UINTN) LocalBbsTable[Idx].BootPriority,
      (UINTN) LocalBbsTable[Idx].Bus,
      (UINTN) LocalBbsTable[Idx].Device,
      (UINTN) LocalBbsTable[Idx].Function,
      (UINTN) LocalBbsTable[Idx].Class,
      (UINTN) LocalBbsTable[Idx].SubClass,
      (UINTN) LocalBbsTable[Idx].DeviceType,
      (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags,
      (UINTN) LocalBbsTable[Idx].BootHandlerSegment,
      (UINTN) LocalBbsTable[Idx].BootHandlerOffset,
      (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset),
      (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset))
      );
  }

  DEBUG ((EFI_D_ERROR, "\n"));
}

EFI_STATUS
BdsRefreshBbsTableForBoot (
  IN BDS_COMMON_OPTION        *Entry
  )
{
  EFI_STATUS                Status;
  UINT16                    HddCount;
  UINT16                    BbsCount;
  HDD_INFO                  *LocalHddInfo;
  BBS_TABLE                 *LocalBbsTable;
  UINT16                    DevType;
  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
  UINTN                     Index;
  UINT16                    Priority;
  UINT16                    *BootOrder;
  UINTN                     BootOrderSize;
  UINT8                     *BootOptionVar;
  UINTN                     BootOptionSize;
  UINT16                    BootOption[100];
  UINT8                     *Ptr;
  UINT16                    DevPathLen;
  EFI_DEVICE_PATH_PROTOCOL  *DevPath;

  HddCount      = 0;
  BbsCount      = 0;
  LocalHddInfo  = NULL;
  LocalBbsTable = NULL;
  DevType       = BBS_UNKNOWN;

  Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &LegacyBios);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  LegacyBios->GetBbsInfo (
                LegacyBios,
                &HddCount,
                &LocalHddInfo,
                &BbsCount,
                &LocalBbsTable
                );
  //
  // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
  // We will set them according to the settings setup by user
  //
  for (Index = 0; Index < BbsCount; Index++) {
    if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) ||
        (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) ||
         (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) {
      LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
    }
  }
  //
  // boot priority always starts at 0
  //
  Priority = 0;
  if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) {
    //
    // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
    //
    DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType;
    Status = BdsSetBootPriority4SameTypeDev (
              DevType,
              LocalBbsTable,
              &Priority
              );
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }
  //
  // we have to set the boot priority for other BBS entries with different device types
  //
  BootOrder = (UINT16 *) BdsLibGetVariableAndSize (
                          L"BootOrder",
                          &gEfiGlobalVariableGuid,
                          &BootOrderSize
                          );
  for (Index = 0; BootOrder && Index < BootOrderSize / sizeof (UINT16); Index++) {
    SPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
    BootOptionVar = BdsLibGetVariableAndSize (
                      BootOption,
                      &gEfiGlobalVariableGuid,
                      &BootOptionSize
                      );
    if (NULL == BootOptionVar) {
      continue;
    }

    Ptr = BootOptionVar;

    Ptr += sizeof (UINT32);
    DevPathLen = *(UINT16 *) Ptr;
    Ptr += sizeof (UINT16);
    Ptr += EfiStrSize ((UINT16 *) Ptr);
    DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
    if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) {
      SafeFreePool (BootOptionVar);
      continue;
    }

    Ptr += DevPathLen;
    if (DevType == ((BBS_TABLE *) Ptr)->DeviceType) {
      //
      // We don't want to process twice for a device type
      //
      SafeFreePool (BootOptionVar);
      continue;
    }

    Status = BdsSetBootPriority4SameTypeDev (
              ((BBS_TABLE *) Ptr)->DeviceType,
              LocalBbsTable,
              &Priority
              );
    SafeFreePool (BootOptionVar);
    if (EFI_ERROR (Status)) {
      break;
    }
  }

  if (BootOrder) {
    SafeFreePool (BootOrder);
  }
  //
  // For debug
  //
  PrintBbsTable (LocalBbsTable);

  return Status;
}

⌨️ 快捷键说明

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