Bug fixes and improvements.
Now to fix the kernel!
This commit is contained in:
parent
1ad2841819
commit
862a6e0c7c
|
@ -38,7 +38,7 @@ EFI_STATUS LoadKernel(EFI_HANDLE ImageHandle, GFX_INFO* Graphics, EFI_CONFIGURAT
|
||||||
EFI_LOADED_IMAGE_PROTOCOL* LoadedImage; // The image here is the BOOTX64.EFI file.
|
EFI_LOADED_IMAGE_PROTOCOL* LoadedImage; // The image here is the BOOTX64.EFI file.
|
||||||
|
|
||||||
/* Connect to the device which contains the file being currently run */
|
/* Connect to the device which contains the file being currently run */
|
||||||
KernelStatus = ST->BootServices->OpenProtocol(ImageHandle, &LoadedImageProtocol, (void**)&LoadedImage, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
KernelStatus = BS->OpenProtocol(ImageHandle, &LoadedImageProtocol, (void**)&LoadedImage, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||||
if (EFI_ERROR(KernelStatus)) {
|
if (EFI_ERROR(KernelStatus)) {
|
||||||
Print(L"Loaded Image Protocol Error: 0x%llx\r\n", KernelStatus);
|
Print(L"Loaded Image Protocol Error: 0x%llx\r\n", KernelStatus);
|
||||||
return KernelStatus;
|
return KernelStatus;
|
||||||
|
@ -50,7 +50,7 @@ EFI_STATUS LoadKernel(EFI_HANDLE ImageHandle, GFX_INFO* Graphics, EFI_CONFIGURAT
|
||||||
|
|
||||||
CHAR16* ESPRoot;
|
CHAR16* ESPRoot;
|
||||||
/* Reinitialize the path to a form we can use */
|
/* Reinitialize the path to a form we can use */
|
||||||
KernelStatus = ST->BootServices->AllocatePool(EfiLoaderData, ESPRootSize, (void**)&ESPRoot);
|
KernelStatus = BS->AllocatePool(EfiLoaderData, ESPRootSize, (void**)&ESPRoot);
|
||||||
|
|
||||||
if (EFI_ERROR(KernelStatus)) {
|
if (EFI_ERROR(KernelStatus)) {
|
||||||
Print(L"ESPRoot Allocate error: 0x%llx\r\n", KernelStatus);
|
Print(L"ESPRoot Allocate error: 0x%llx\r\n", KernelStatus);
|
||||||
|
@ -68,7 +68,7 @@ EFI_STATUS LoadKernel(EFI_HANDLE ImageHandle, GFX_INFO* Graphics, EFI_CONFIGURAT
|
||||||
// Get a reference to the FileSystem protocol, which allows us to access files.
|
// Get a reference to the FileSystem protocol, which allows us to access files.
|
||||||
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* FileSystem;
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* FileSystem;
|
||||||
|
|
||||||
KernelStatus = ST->BootServices->OpenProtocol(LoadedImage->DeviceHandle, &FileSystemProtocol, (void**)&FileSystem, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
KernelStatus = BS->OpenProtocol(LoadedImage->DeviceHandle, &FileSystemProtocol, (void**)&FileSystem, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||||
if (EFI_ERROR(KernelStatus)) {
|
if (EFI_ERROR(KernelStatus)) {
|
||||||
Print(L"FileSystem OpenProtocol error: 0x%llx\r\n", KernelStatus);
|
Print(L"FileSystem OpenProtocol error: 0x%llx\r\n", KernelStatus);
|
||||||
return KernelStatus;
|
return KernelStatus;
|
||||||
|
@ -108,7 +108,7 @@ EFI_STATUS LoadKernel(EFI_HANDLE ImageHandle, GFX_INFO* Graphics, EFI_CONFIGURAT
|
||||||
ConfigFilePrefixLength += 1; // Path ends with '\'
|
ConfigFilePrefixLength += 1; // Path ends with '\'
|
||||||
|
|
||||||
#ifdef LOADER_DEBUG_MAIN
|
#ifdef LOADER_DEBUG_MAIN
|
||||||
Print(L"BootFilePathLength: %llu, TextFilePathLength: %llu, BootfilePath size: %llu\r\n", BootFilePathLength, ConfigFilePrefixLength, StrSize(BootFilePath));
|
Print(L"BootFilePathLength: %llu, ConfigFilePath Length: %llu, BootloaderPath size: %llu\r\n", BootFilePathLength, ConfigFilePrefixLength, StrSize(BootFilePath));
|
||||||
AwaitKey(L'\0');
|
AwaitKey(L'\0');
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ EFI_STATUS LoadKernel(EFI_HANDLE ImageHandle, GFX_INFO* Graphics, EFI_CONFIGURAT
|
||||||
|
|
||||||
CHAR16* ConfigFilePath;
|
CHAR16* ConfigFilePath;
|
||||||
|
|
||||||
KernelStatus = ST->BootServices->AllocatePool(EfiBootServicesData, ConfigFilePathSize, (void**)&ConfigFilePath);
|
KernelStatus = BS->AllocatePool(EfiBootServicesData, ConfigFilePathSize, (void**)&ConfigFilePath);
|
||||||
if (EFI_ERROR(KernelStatus)) {
|
if (EFI_ERROR(KernelStatus)) {
|
||||||
Print(L"ConfigFile Path Allocate error: 0x%llx\r\n", KernelStatus);
|
Print(L"ConfigFile Path Allocate error: 0x%llx\r\n", KernelStatus);
|
||||||
return KernelStatus;
|
return KernelStatus;
|
||||||
|
@ -144,6 +144,7 @@ EFI_STATUS LoadKernel(EFI_HANDLE ImageHandle, GFX_INFO* Graphics, EFI_CONFIGURAT
|
||||||
return KernelStatus;
|
return KernelStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef LOADER_DEBUG_MAIN
|
#ifdef LOADER_DEBUG_MAIN
|
||||||
AwaitKey(L"bootconf.txt file opened.\r\n");
|
AwaitKey(L"bootconf.txt file opened.\r\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -185,9 +186,10 @@ EFI_STATUS LoadKernel(EFI_HANDLE ImageHandle, GFX_INFO* Graphics, EFI_CONFIGURAT
|
||||||
|
|
||||||
Print(L"Filename: %s\r\n", ConfigFileInfo->FileName);
|
Print(L"Filename: %s\r\n", ConfigFileInfo->FileName);
|
||||||
Print(L"Size: %llu\r\n", ConfigFileInfo->Size);
|
Print(L"Size: %llu\r\n", ConfigFileInfo->Size);
|
||||||
Print(L"Filesize: %llu\r\n", ConfigFileInfo->FileName);
|
Print(L"Filesize: %llu\r\n", ConfigFileInfo->FileSize);
|
||||||
Print(L"PhysicalSize: %llu\r\n", ConfigFileInfo->PhysicalSize);
|
Print(L"Size on disk: %llu (%llu pages)\r\n", ConfigFileInfo->PhysicalSize, (ConfigFileInfo->PhysicalSize / 4096));
|
||||||
Print(L"Attribute: %llx\r\n", ConfigFileInfo->Attribute);
|
Print(L"Attribute: %llx\r\n", ConfigFileInfo->Attribute);
|
||||||
|
Print(L"Chracter length: %llu\r\n", ConfigFileInfo->FileSize >> 1);
|
||||||
|
|
||||||
Print(L"Created: %02hhu/%02hhu/%04hu - %02hhu:%02hhu:%02hhu.%u\r\n", ConfigFileInfo->CreateTime.Month, ConfigFileInfo->CreateTime.Day, ConfigFileInfo->CreateTime.Year, ConfigFileInfo->CreateTime.Hour, ConfigFileInfo->CreateTime.Minute, ConfigFileInfo->CreateTime.Second, ConfigFileInfo->CreateTime.Nanosecond);
|
Print(L"Created: %02hhu/%02hhu/%04hu - %02hhu:%02hhu:%02hhu.%u\r\n", ConfigFileInfo->CreateTime.Month, ConfigFileInfo->CreateTime.Day, ConfigFileInfo->CreateTime.Year, ConfigFileInfo->CreateTime.Hour, ConfigFileInfo->CreateTime.Minute, ConfigFileInfo->CreateTime.Second, ConfigFileInfo->CreateTime.Nanosecond);
|
||||||
Print(L"Last Modified: %02hhu/%02hhu/%04hu - %02hhu:%02hhu:%02hhu.%u\r\n", ConfigFileInfo->ModificationTime.Month, ConfigFileInfo->ModificationTime.Day, ConfigFileInfo->ModificationTime.Year, ConfigFileInfo->ModificationTime.Hour, ConfigFileInfo->ModificationTime.Minute, ConfigFileInfo->ModificationTime.Second, ConfigFileInfo->ModificationTime.Nanosecond);
|
Print(L"Last Modified: %02hhu/%02hhu/%04hu - %02hhu:%02hhu:%02hhu.%u\r\n", ConfigFileInfo->ModificationTime.Month, ConfigFileInfo->ModificationTime.Day, ConfigFileInfo->ModificationTime.Year, ConfigFileInfo->ModificationTime.Hour, ConfigFileInfo->ModificationTime.Minute, ConfigFileInfo->ModificationTime.Second, ConfigFileInfo->ModificationTime.Nanosecond);
|
||||||
|
@ -218,12 +220,12 @@ EFI_STATUS LoadKernel(EFI_HANDLE ImageHandle, GFX_INFO* Graphics, EFI_CONFIGURAT
|
||||||
|
|
||||||
uint16_t BOM = UTF16_BOM_LE;
|
uint16_t BOM = UTF16_BOM_LE;
|
||||||
|
|
||||||
if (!Compare(KernelConfigArray, BOM, 2)) {
|
if (!Compare(KernelConfigArray, &BOM, 2)) {
|
||||||
// The file doesn't have the BOM mark.
|
// The file doesn't have the BOM mark.
|
||||||
// Just to make sure, we should check if the file was encoded on a Big Endian system.
|
// Just to make sure, we should check if the file was encoded on a Big Endian system.
|
||||||
BOM = UTF16_BOM_BE;
|
BOM = UTF16_BOM_BE;
|
||||||
|
|
||||||
if (Compare(KernelConfigArray, BOM, 2))
|
if (Compare(KernelConfigArray, &BOM, 2))
|
||||||
Print(L"%EError: bootconf.txt was made on a Big-Endian system. Please convert it or use a Little-Endian system.%N\r\n");
|
Print(L"%EError: bootconf.txt was made on a Big-Endian system. Please convert it or use a Little-Endian system.%N\r\n");
|
||||||
else
|
else
|
||||||
// There is no BOM mark.
|
// There is no BOM mark.
|
||||||
|
@ -235,19 +237,27 @@ EFI_STATUS LoadKernel(EFI_HANDLE ImageHandle, GFX_INFO* Graphics, EFI_CONFIGURAT
|
||||||
|
|
||||||
size_t KernelPathSize = 0, FirstLineLength = 0;
|
size_t KernelPathSize = 0, FirstLineLength = 0;
|
||||||
|
|
||||||
|
Print(L"Kernel Config file contains: %s\r\n", KernelConfigArray);
|
||||||
|
|
||||||
for (size_t i = 1 /* Skip the BOM */; i < ((ConfigFileInfo->FileSize) >> 1) /* UTF-16 characters are 2 bytes long, so we divide by 2 to get the number of characters */; i++) {
|
for (size_t i = 1 /* Skip the BOM */; i < ((ConfigFileInfo->FileSize) >> 1) /* UTF-16 characters are 2 bytes long, so we divide by 2 to get the number of characters */; i++) {
|
||||||
if (KernelConfigArray[i] == L'\n') {
|
if (KernelConfigArray[i] == L'\n') {
|
||||||
FirstLineLength = i + 1; // Account for the extra character.
|
FirstLineLength = i + 1; // Account for the extra character.
|
||||||
|
#ifdef LOADER_DEBUG_MAIN
|
||||||
|
Print(L"Newline at character %llx in Config file.\r\n", i);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (KernelConfigArray[i] = L'\r') {
|
else if (KernelConfigArray[i] == L'\r') {
|
||||||
FirstLineLength = i + 2; // There will be an \n after the \r
|
FirstLineLength = i + 2; // There will be an \n after the \r
|
||||||
|
#ifdef LOADER_DEBUG_MAIN
|
||||||
|
Print(L"Ret-Newline at character %llx in Config file.\r\n", i);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (KernelConfigArray[i] != L' ')
|
if (KernelConfigArray[i] != L' ') {
|
||||||
KernelPathSize++;
|
KernelPathSize++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t KernelPathLength = KernelPathSize;
|
size_t KernelPathLength = KernelPathSize;
|
||||||
|
@ -304,12 +314,12 @@ EFI_STATUS LoadKernel(EFI_HANDLE ImageHandle, GFX_INFO* Graphics, EFI_CONFIGURAT
|
||||||
|
|
||||||
AwaitKey(L"Loading kernel image.\r\n");
|
AwaitKey(L"Loading kernel image.\r\n");
|
||||||
|
|
||||||
KernelStatus = BS->FreePool(ConfigFilePath);
|
/*KernelStatus = BS->FreePool(ConfigFilePath);
|
||||||
if (EFI_ERROR(KernelStatus)) {
|
if (EFI_ERROR(KernelStatus)) {
|
||||||
Print(L"ConfigFilePath Free error: 0x%llx\r\n", KernelStatus);
|
Print(L"ConfigFilePath Free error: 0x%llx\r\n", KernelStatus);
|
||||||
return KernelStatus;
|
return KernelStatus;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
KernelStatus = BS->FreePool(KernelConfigArray);
|
KernelStatus = BS->FreePool(KernelConfigArray);
|
||||||
if (EFI_ERROR(KernelStatus)) {
|
if (EFI_ERROR(KernelStatus)) {
|
||||||
Print(L"KernelConfigArray Free error: 0x%llx\r\n", KernelStatus);
|
Print(L"KernelConfigArray Free error: 0x%llx\r\n", KernelStatus);
|
||||||
|
|
47
src/gfx.c
47
src/gfx.c
|
@ -203,7 +203,7 @@ EFI_STATUS InitGfx(EFI_HANDLE ImageHandle, GFX_INFO* Graphics) {
|
||||||
return GfxStatus;
|
return GfxStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue; // It isn't.
|
continue; // It doesn't.
|
||||||
}
|
}
|
||||||
else if (GfxStatus != EFI_ALREADY_STARTED)
|
else if (GfxStatus != EFI_ALREADY_STARTED)
|
||||||
continue; // Ditto.
|
continue; // Ditto.
|
||||||
|
@ -272,20 +272,29 @@ EFI_STATUS InitGfx(EFI_HANDLE ImageHandle, GFX_INFO* Graphics) {
|
||||||
|
|
||||||
// And again, for the child of the controller.
|
// And again, for the child of the controller.
|
||||||
GfxStatus = Name2Device->GetControllerName(Name2Device, DevicePathHandles[ControllerIndex], GraphicsHandles[DeviceInd], Language, &ChildDisplayName);
|
GfxStatus = Name2Device->GetControllerName(Name2Device, DevicePathHandles[ControllerIndex], GraphicsHandles[DeviceInd], Language, &ChildDisplayName);
|
||||||
if (GfxStatus == EFI_UNSUPPORTED)
|
if (GfxStatus == EFI_UNSUPPORTED) {
|
||||||
{
|
|
||||||
GfxStatus = Name2Device->GetControllerName(Name2Device, DevicePathHandles[ControllerIndex], GraphicsHandles[DeviceInd], Language2, &ChildDisplayName);
|
GfxStatus = Name2Device->GetControllerName(Name2Device, DevicePathHandles[ControllerIndex], GraphicsHandles[DeviceInd], Language2, &ChildDisplayName);
|
||||||
if (GfxStatus == EFI_UNSUPPORTED)
|
if (GfxStatus == EFI_UNSUPPORTED) {
|
||||||
{
|
|
||||||
GfxStatus = Name2Device->GetControllerName(Name2Device, DevicePathHandles[ControllerIndex], GraphicsHandles[DeviceInd], Language3, &ChildDisplayName);
|
GfxStatus = Name2Device->GetControllerName(Name2Device, DevicePathHandles[ControllerIndex], GraphicsHandles[DeviceInd], Language3, &ChildDisplayName);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (EFI_ERROR(GfxStatus))
|
|
||||||
{
|
|
||||||
|
if (EFI_ERROR(GfxStatus)) {
|
||||||
|
|
||||||
#ifdef GFX_DEBUG_NAMING
|
#ifdef GFX_DEBUG_NAMING
|
||||||
Print(L"Name2Device GetController ChildName error: 0x%llx\r\n", GfxStatus);
|
Print(L"Name2Device GetController ChildName error: 0x%llx\r\n", GfxStatus);
|
||||||
#endif
|
#endif
|
||||||
|
if (GfxStatus == EFI_UNSUPPORTED) {
|
||||||
|
Print(L"First 10 characters of the supported language:\r\n");
|
||||||
|
for (uint32_t p = 0; p < 10; p++) {
|
||||||
|
Print(L"%c", Name2Device->SupportedLanguages[p]);
|
||||||
|
}
|
||||||
|
Print(L"\r\n");
|
||||||
|
AwaitKey(L"\0");
|
||||||
|
}
|
||||||
|
|
||||||
ChildDisplayName = DefaultChildName;
|
ChildDisplayName = DefaultChildName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +362,7 @@ EFI_STATUS InitGfx(EFI_HANDLE ImageHandle, GFX_INFO* Graphics) {
|
||||||
// We have something in the controller
|
// We have something in the controller
|
||||||
|
|
||||||
#ifdef GFX_DEBUG_NAMING
|
#ifdef GFX_DEBUG_NAMING
|
||||||
Print(L"ef. DevicePath_GraphicsHandle matched DevicePath_Graphics &llu, ControllerIndex: &llu\r\n", DeviceInd, ControllerIndex);
|
Print(L"ef. DevicePath_GraphicsHandle matched DevicePath_Graphics %llu, ControllerIndex: %llu\r\n", DeviceInd, ControllerIndex);
|
||||||
#endif
|
#endif
|
||||||
for (size_t Name2DriverIndex = 0; Name2DriverIndex < NumName2Handles; Name2DriverIndex++) {
|
for (size_t Name2DriverIndex = 0; Name2DriverIndex < NumName2Handles; Name2DriverIndex++) {
|
||||||
EFI_COMPONENT_NAME2_PROTOCOL* Name2Device;
|
EFI_COMPONENT_NAME2_PROTOCOL* Name2Device;
|
||||||
|
@ -492,6 +501,14 @@ EFI_STATUS InitGfx(EFI_HANDLE ImageHandle, GFX_INFO* Graphics) {
|
||||||
AwaitKey(L"\0");
|
AwaitKey(L"\0");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (GfxStatus == EFI_UNSUPPORTED) {
|
||||||
|
|
||||||
|
POOL_PRINT StringName = { 0 };
|
||||||
|
CatPrint(&StringName, L"%c. Weird device @ Memory Address 0x%llx (is this in a VM?)\r\n", DeviceInd + 0x30, GraphicsHandles[DeviceInd]);
|
||||||
|
NameBuffer[DeviceInd] = StringName.str;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (EFI_ERROR(GfxStatus)) {
|
else if (EFI_ERROR(GfxStatus)) {
|
||||||
Print(L"GraphicsHandles DevicePath_Graphics OpenProtocol error. 0x%llx\r\n", GfxStatus);
|
Print(L"GraphicsHandles DevicePath_Graphics OpenProtocol error. 0x%llx\r\n", GfxStatus);
|
||||||
|
@ -517,9 +534,11 @@ EFI_STATUS InitGfx(EFI_HANDLE ImageHandle, GFX_INFO* Graphics) {
|
||||||
DeviceInd = 2;
|
DeviceInd = 2;
|
||||||
size_t Timeout = GFX_TIMEOUT; // There's a 5 minute watchdog timer, but in debug mode that's disabled.
|
size_t Timeout = GFX_TIMEOUT; // There's a 5 minute watchdog timer, but in debug mode that's disabled.
|
||||||
|
|
||||||
while (0x30 > Key.UnicodeChar || Key.UnicodeChar > 0x33) {
|
//while ((Key.UnicodeChar != '0') || (Key.UnicodeChar != '1') || (Key.UnicodeChar != '2') || (Key.UnicodeChar != '3')) {
|
||||||
for (size_t DeviceNumber = 0; DeviceNumber < NumGfxHandles; DeviceNumber++)
|
for (size_t DeviceNumber = 0; DeviceNumber < NumGfxHandles; DeviceNumber++) {
|
||||||
Print(L"%s", NameBuffer[DeviceNumber]);
|
Print(L"%s", NameBuffer[DeviceNumber]);
|
||||||
|
}
|
||||||
|
|
||||||
Print(L"\r\n");
|
Print(L"\r\n");
|
||||||
|
|
||||||
Print(L"%E==================== Graphics Configuration ==================== %N \r\n");
|
Print(L"%E==================== Graphics Configuration ==================== %N \r\n");
|
||||||
|
@ -532,6 +551,7 @@ EFI_STATUS InitGfx(EFI_HANDLE ImageHandle, GFX_INFO* Graphics) {
|
||||||
|
|
||||||
while (Timeout) {
|
while (Timeout) {
|
||||||
Print(L"Please select an option. Defaulting to %llu in %llu .\r", DeviceInd, Timeout);
|
Print(L"Please select an option. Defaulting to %llu in %llu .\r", DeviceInd, Timeout);
|
||||||
|
GfxStatus = WaitForSingleEvent(ST->ConIn->WaitForKey, 10000000);
|
||||||
if (GfxStatus != EFI_TIMEOUT) {
|
if (GfxStatus != EFI_TIMEOUT) {
|
||||||
GfxStatus = ST->ConIn->ReadKeyStroke(ST->ConIn, &Key);
|
GfxStatus = ST->ConIn->ReadKeyStroke(ST->ConIn, &Key);
|
||||||
if (EFI_ERROR(GfxStatus)) {
|
if (EFI_ERROR(GfxStatus)) {
|
||||||
|
@ -544,6 +564,11 @@ EFI_STATUS InitGfx(EFI_HANDLE ImageHandle, GFX_INFO* Graphics) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Timeout -= 1;
|
Timeout -= 1;
|
||||||
|
|
||||||
|
if (!Timeout) {
|
||||||
|
Print(L"Defaulting to option %llu.\r\n\n", DeviceInd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Timeout)
|
if (Timeout)
|
||||||
|
@ -555,7 +580,7 @@ EFI_STATUS InitGfx(EFI_HANDLE ImageHandle, GFX_INFO* Graphics) {
|
||||||
Print(L"Error resetting input buffer: 0x%llx\r\n", GfxStatus);
|
Print(L"Error resetting input buffer: 0x%llx\r\n", GfxStatus);
|
||||||
return GfxStatus;
|
return GfxStatus;
|
||||||
}
|
}
|
||||||
}
|
//}
|
||||||
|
|
||||||
if ((NumGfxHandles > 1) && (DeviceInd == 0)) {
|
if ((NumGfxHandles > 1) && (DeviceInd == 0)) {
|
||||||
// Configure each device individually
|
// Configure each device individually
|
||||||
|
|
Loading…
Reference in New Issue
Block a user