]> code.delx.au - refind/blobdiff - EfiLib/legacy.c
Significant improvements to legacy-mode boot support, particularly on
[refind] / EfiLib / legacy.c
index 3aae71d7610d6e9943900422b9ee65b09ebda52c..4578da0b3105f053efa13c88e37e0b1f29c5757a 100644 (file)
@@ -22,6 +22,8 @@ BOOT_OPTION_BBS_MAPPING  *mBootOptionBbsMapping     = NULL;
 UINTN                    mBootOptionBbsMappingCount = 0;
 
 extern EFI_DEVICE_PATH EndDevicePath[];
+extern EFI_GUID gEfiLegacyBiosProtocolGuid;
+EFI_GUID gEfiLegacyDevOrderVariableGuid     = { 0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52 }};
 
 /**
 
@@ -968,7 +970,7 @@ BdsDeleteAllInvalidLegacyBootOptions (
         return EFI_OUT_OF_RESOURCES;
       }
     }
-  
+
     //
     // Skip Non-Legacy boot option
     // 
@@ -1041,323 +1043,165 @@ BdsDeleteAllInvalidLegacyBootOptions (
 }
 
 /**
-  Add the legacy boot devices from BBS table into 
-  the legacy device boot order.
-
-  @retval EFI_SUCCESS           The boot devices are added successfully.
-  @retval EFI_NOT_FOUND         The legacy boot devices are not found.
-  @retval EFI_OUT_OF_RESOURCES  Memmory or storage is not enough.
-  @retval EFI_DEVICE_ERROR      Fail to add the legacy device boot order into EFI variable
-                                because of hardware error.
+  Fill the device order buffer.
+
+  @param BbsTable        The BBS table.
+  @param BbsType         The BBS Type.
+  @param BbsCount        The BBS Count.
+  @param Buf             device order buffer.
+
+  @return The device order buffer.
+
 **/
-// EFI_STATUS
-// EFIAPI
-// BdsUpdateLegacyDevOrder (
-//   VOID
-//   )
-// {
-//   LEGACY_DEV_ORDER_ENTRY      *DevOrder;
-//   LEGACY_DEV_ORDER_ENTRY      *NewDevOrder;
-//   LEGACY_DEV_ORDER_ENTRY      *Ptr;
-//   LEGACY_DEV_ORDER_ENTRY      *NewPtr;
-//   UINTN                       DevOrderSize;
-//   EFI_LEGACY_BIOS_PROTOCOL    *LegacyBios;
-//   EFI_STATUS                  Status;
-//   UINT16                      HddCount;
-//   UINT16                      BbsCount;
-//   HDD_INFO                    *LocalHddInfo;
-//   BBS_TABLE                   *LocalBbsTable;
-//   UINTN                       Index;
-//   UINTN                       Index2;
-//   UINTN                       *Idx;
-//   UINTN                       FDCount;
-//   UINTN                       HDCount;
-//   UINTN                       CDCount;
-//   UINTN                       NETCount;
-//   UINTN                       BEVCount;
-//   UINTN                       TotalSize;
-//   UINTN                       HeaderSize;
-//   UINT16                      *NewFDPtr;
-//   UINT16                      *NewHDPtr;
-//   UINT16                      *NewCDPtr;
-//   UINT16                      *NewNETPtr;
-//   UINT16                      *NewBEVPtr;
-//   UINT16                      *NewDevPtr;
-//   UINTN                       FDIndex;
-//   UINTN                       HDIndex;
-//   UINTN                       CDIndex;
-//   UINTN                       NETIndex;
-//   UINTN                       BEVIndex;
-// 
-//   Idx           = NULL;
-//   FDCount       = 0;
-//   HDCount       = 0;
-//   CDCount       = 0;
-//   NETCount      = 0;
-//   BEVCount      = 0;
-//   TotalSize     = 0;
-//   HeaderSize    = sizeof (BBS_TYPE) + sizeof (UINT16);
-//   FDIndex       = 0;
-//   HDIndex       = 0;
-//   CDIndex       = 0;
-//   NETIndex      = 0;
-//   BEVIndex      = 0;
-//   NewDevPtr     = NULL;
-// 
-//   Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
-//   if (EFI_ERROR (Status)) {
-//     return Status;
-//   }
-// 
-//   Status = LegacyBios->GetBbsInfo (
-//                          LegacyBios,
-//                          &HddCount,
-//                          &LocalHddInfo,
-//                          &BbsCount,
-//                          &LocalBbsTable
-//                          );
-//   if (EFI_ERROR (Status)) {
-//     return Status;
-//   }
-// 
-//   DevOrder = BdsLibGetVariableAndSize (
-//                VAR_LEGACY_DEV_ORDER,
-//                &gEfiLegacyDevOrderVariableGuid,
-//                &DevOrderSize
-//                );
-//   if (NULL == DevOrder) {
-//     return BdsCreateDevOrder (LocalBbsTable, BbsCount);
-//   }
-//   //
-//   // First we figure out how many boot devices with same device type respectively
-//   //
-//   for (Index = 0; Index < BbsCount; Index++) {
-//     if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
-//         (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
-//         ) {
-//       continue;
-//     }
-// 
-//     switch (LocalBbsTable[Index].DeviceType) {
-//     case BBS_FLOPPY:
-//       FDCount++;
-//       break;
-// 
-//     case BBS_HARDDISK:
-//       HDCount++;
-//       break;
-// 
-//     case BBS_CDROM:
-//       CDCount++;
-//       break;
-// 
-//     case BBS_EMBED_NETWORK:
-//       NETCount++;
-//       break;
-// 
-//     case BBS_BEV_DEVICE:
-//       BEVCount++;
-//       break;
-// 
-//     default:
-//       break;
-//     }
-//   }
-// 
-//   TotalSize += (HeaderSize + FDCount * sizeof (UINT16));
-//   TotalSize += (HeaderSize + HDCount * sizeof (UINT16));
-//   TotalSize += (HeaderSize + CDCount * sizeof (UINT16));
-//   TotalSize += (HeaderSize + NETCount * sizeof (UINT16));
-//   TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));
-// 
-//   NewDevOrder = AllocateZeroPool (TotalSize);
-//   if (NULL == NewDevOrder) {
-//     return EFI_OUT_OF_RESOURCES;
-//   }
-// 
-// 
-// 
-//   //
-//   // copy FD
-//   //
-//   Ptr             = DevOrder;
-//   NewPtr          = NewDevOrder;
-//   NewPtr->BbsType = Ptr->BbsType;
-//   NewPtr->Length  = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
-//   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
-//     if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
-//         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
-//         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_FLOPPY
-//         ) {
-//       continue;
-//     }
-// 
-//     NewPtr->Data[FDIndex] = Ptr->Data[Index];
-//     FDIndex++;
-//   }
-//   NewFDPtr = NewPtr->Data;
-// 
-//   //
-//   // copy HD
-//   //
-//   Ptr             = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
-//   NewPtr          = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
-//   NewPtr->BbsType = Ptr->BbsType;
-//   NewPtr->Length  = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
-//   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
-//     if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
-//         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
-//         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||
-//         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_HARDDISK
-//         ) {
-//       continue;
-//     }
-// 
-//     NewPtr->Data[HDIndex] = Ptr->Data[Index];
-//     HDIndex++;
-//   }
-//   NewHDPtr = NewPtr->Data;
-// 
-//   //
-//   // copy CD
-//   //
-//   Ptr    = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
-//   NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
-//   NewPtr->BbsType = Ptr->BbsType;
-//   NewPtr->Length  = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
-//   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
-//     if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
-//         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
-//         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||
-//         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_CDROM
-//         ) {
-//       continue;
-//     }
-// 
-//     NewPtr->Data[CDIndex] = Ptr->Data[Index];
-//     CDIndex++;
-//   }
-//   NewCDPtr = NewPtr->Data;
-// 
-//   //
-//   // copy NET
-//   //
-//   Ptr    = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
-//   NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
-//   NewPtr->BbsType = Ptr->BbsType;
-//   NewPtr->Length  = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
-//   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
-//     if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
-//         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
-//         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||
-//         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_EMBED_NETWORK
-//         ) {
-//       continue;
-//     }
-// 
-//     NewPtr->Data[NETIndex] = Ptr->Data[Index];
-//     NETIndex++;
-//   }
-//   NewNETPtr = NewPtr->Data;
-//   
-//   //
-//   // copy BEV
-//   //
-//   Ptr    = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
-//   NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
-//   NewPtr->BbsType = Ptr->BbsType;
-//   NewPtr->Length  = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
-//   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
-//     if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
-//         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
-//         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||
-//         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_BEV_DEVICE
-//         ) {
-//       continue;
-//     }
-// 
-//     NewPtr->Data[BEVIndex] = Ptr->Data[Index];
-//     BEVIndex++;
-//   }
-//   NewBEVPtr = NewPtr->Data;
-// 
-//   for (Index = 0; Index < BbsCount; Index++) {
-//     if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
-//         (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
-//         ) {
-//       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 != NULL) {
-//       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
-//         // insert it before disabled indexes.
-//         //
-//         for (Index2 = 0; Index2 < *Idx; Index2++) {
-//           if ((NewDevPtr[Index2] & 0xFF00) == 0xFF00) {
-//             break;
-//           }
-//         }
-//         CopyMem (&NewDevPtr[Index2 + 1], &NewDevPtr[Index2], (*Idx - Index2) * sizeof (UINT16));
-//         NewDevPtr[Index2] = (UINT16) (Index & 0xFF);
-//         (*Idx)++;
-//       }
-//     }
-//   }
-// 
-//   FreePool (DevOrder);
-// 
-//   Status = gRT->SetVariable (
-//                   VAR_LEGACY_DEV_ORDER,
-//                   &gEfiLegacyDevOrderVariableGuid,
-//                   VAR_FLAG,
-//                   TotalSize,
-//                   NewDevOrder
-//                   );
-//   FreePool (NewDevOrder);
-// 
-//   return Status;
-// }
+UINT16 *
+BdsFillDevOrderBuf (
+  IN BBS_TABLE                    *BbsTable,
+  IN BBS_TYPE                     BbsType,
+  IN UINTN                        BbsCount,
+  OUT UINT16                      *Buf
+  )
+{
+  UINTN Index;
+
+  for (Index = 0; Index < BbsCount; Index++) {
+    if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
+      continue;
+    }
+
+    if (BbsTable[Index].DeviceType != BbsType) {
+      continue;
+    }
+
+    *Buf = (UINT16) (Index & 0xFF);
+    Buf++;
+  }
+
+  return Buf;
+}
+
+/**
+  Create the device order buffer.
+
+  @param BbsTable        The BBS table.
+  @param BbsCount        The BBS Count.
+
+  @retval EFI_SUCCES             The buffer is created and the EFI variable named 
+                                 VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid is
+                                 set correctly.
+  @retval EFI_OUT_OF_RESOURCES   Memmory or storage is not enough.
+  @retval EFI_DEVICE_ERROR       Fail to add the device order into EFI variable fail
+                                 because of hardware error.
+**/
+EFI_STATUS
+BdsCreateDevOrder (
+  IN BBS_TABLE                  *BbsTable,
+  IN UINT16                     BbsCount
+  )
+{
+  UINTN                       Index;
+  UINTN                       FDCount;
+  UINTN                       HDCount;
+  UINTN                       CDCount;
+  UINTN                       NETCount;
+  UINTN                       BEVCount;
+  UINTN                       TotalSize;
+  UINTN                       HeaderSize;
+  LEGACY_DEV_ORDER_ENTRY      *DevOrder;
+  LEGACY_DEV_ORDER_ENTRY      *DevOrderPtr;
+  EFI_STATUS                  Status;
+
+  FDCount     = 0;
+  HDCount     = 0;
+  CDCount     = 0;
+  NETCount    = 0;
+  BEVCount    = 0;
+  TotalSize   = 0;
+  HeaderSize  = sizeof (BBS_TYPE) + sizeof (UINT16);
+  DevOrder    = NULL;
+  Status      = EFI_SUCCESS;
+
+  //
+  // Count all boot devices
+  //
+  for (Index = 0; Index < BbsCount; Index++) {
+    if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
+      continue;
+    }
+
+    switch (BbsTable[Index].DeviceType) {
+    case BBS_FLOPPY:
+      FDCount++;
+      break;
+
+    case BBS_HARDDISK:
+      HDCount++;
+      break;
+
+    case BBS_CDROM:
+      CDCount++;
+      break;
+
+    case BBS_EMBED_NETWORK:
+      NETCount++;
+      break;
+
+    case BBS_BEV_DEVICE:
+      BEVCount++;
+      break;
 
+    default:
+      break;
+    }
+  }
+
+  TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);
+  TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);
+  TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);
+  TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);
+  TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);
+
+  //
+  // Create buffer to hold all boot device order
+  //
+  DevOrder = AllocateZeroPool (TotalSize);
+  if (NULL == DevOrder) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  DevOrderPtr          = DevOrder;
+
+  DevOrderPtr->BbsType = BBS_FLOPPY;
+  DevOrderPtr->Length  = (UINT16) (sizeof (DevOrderPtr->Length) + FDCount * sizeof (UINT16));
+  DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, DevOrderPtr->Data);
+
+  DevOrderPtr->BbsType = BBS_HARDDISK;
+  DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
+  DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, DevOrderPtr->Data);
+  
+  DevOrderPtr->BbsType = BBS_CDROM;
+  DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
+  DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, DevOrderPtr->Data);
+  
+  DevOrderPtr->BbsType = BBS_EMBED_NETWORK;
+  DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
+  DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, DevOrderPtr->Data);
+
+  DevOrderPtr->BbsType = BBS_BEV_DEVICE;
+  DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
+  DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, DevOrderPtr->Data);
+
+  ASSERT (TotalSize == (UINTN) ((UINT8 *) DevOrderPtr - (UINT8 *) DevOrder));
+
+  //
+  // Save device order for legacy boot device to variable.
+  //
+  Status = gRT->SetVariable (
+                  VAR_LEGACY_DEV_ORDER,
+                  &gEfiLegacyDevOrderVariableGuid,
+                  VAR_FLAG,
+                  TotalSize,
+                  DevOrder
+                  );
+  FreePool (DevOrder);
+
+  return Status;
+}