diff --git a/arch/i386/hardware.c b/arch/i386/hardware.c index a7c8a894abb..87d8c653e73 100644 --- a/arch/i386/hardware.c +++ b/arch/i386/hardware.c @@ -2,6 +2,7 @@ * FreeLoader * * Copyright (C) 2003, 2004 Eric Kohl + * Copyright (C) 2006 Aleksey Bragin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,6 +24,10 @@ #define NDEBUG #include +/* Parts of hardware detection specific to ReactOS */ +/* They should go away once kernel is able to use configuration lists */ +#define ROS_SPECIFIC 1 + #define MILLISEC (10) #define PRECISION (8) @@ -117,7 +122,7 @@ typedef struct _CM_PNP_BIOS_INSTALLATION_CHECK } __attribute__((packed)) CM_PNP_BIOS_INSTALLATION_CHECK, *PCM_PNP_BIOS_INSTALLATION_CHECK; -static WCHAR Hex[] = L"0123456789ABCDEF"; +static CHAR Hex[] = "0123456789abcdef"; static unsigned int delay_count = 1; extern ULONG reactos_disk_count; @@ -423,90 +428,45 @@ DetectPnpBios(FRLDRHKEY SystemKey, ULONG *BusNumber) static VOID -SetHarddiskConfigurationData(FRLDRHKEY DiskKey, +SetHarddiskConfigurationData(PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry, ULONG DriveNumber) { - PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; - PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry; - EXTENDED_GEOMETRY ExtGeometry; - GEOMETRY Geometry; - ULONG Size; - LONG Error; + EXTENDED_GEOMETRY ExtGeometry; + GEOMETRY Geometry; - /* Set 'Configuration Data' value */ - Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + - sizeof(CM_DISK_GEOMETRY_DEVICE_DATA); - FullResourceDescriptor = MmAllocateMemory(Size); - if (FullResourceDescriptor == NULL) - { - DbgPrint((DPRINT_HWDETECT, - "Failed to allocate a full resource descriptor\n")); - return; - } - - memset(FullResourceDescriptor, 0, Size); - FullResourceDescriptor->InterfaceType = InterfaceTypeUndefined; - FullResourceDescriptor->BusNumber = 0; - FullResourceDescriptor->PartialResourceList.Version = 1; - FullResourceDescriptor->PartialResourceList.Revision = 1; - FullResourceDescriptor->PartialResourceList.Count = 1; - FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Type = - CmResourceTypeDeviceSpecific; -// FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].ShareDisposition = -// FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Flags = - FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize = - sizeof(CM_DISK_GEOMETRY_DEVICE_DATA); - - /* Get pointer to geometry data */ - DiskGeometry = (PVOID)(((ULONG_PTR)FullResourceDescriptor) + sizeof(CM_FULL_RESOURCE_DESCRIPTOR)); - - /* Get the disk geometry */ - ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY); - if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size)) - { - DiskGeometry->BytesPerSector = ExtGeometry.BytesPerSector; - DiskGeometry->NumberOfCylinders = ExtGeometry.Cylinders; - DiskGeometry->SectorsPerTrack = ExtGeometry.SectorsPerTrack; - DiskGeometry->NumberOfHeads = ExtGeometry.Heads; - } - else if(MachDiskGetDriveGeometry(DriveNumber, &Geometry)) - { - DiskGeometry->BytesPerSector = Geometry.BytesPerSector; - DiskGeometry->NumberOfCylinders = Geometry.Cylinders; - DiskGeometry->SectorsPerTrack = Geometry.Sectors; - DiskGeometry->NumberOfHeads = Geometry.Heads; - } - else - { - DbgPrint((DPRINT_HWDETECT, "Reading disk geometry failed\n")); - MmFreeMemory(FullResourceDescriptor); - return; - } - DbgPrint((DPRINT_HWDETECT, - "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n", - DriveNumber, - DiskGeometry->NumberOfCylinders, - DiskGeometry->NumberOfHeads, - DiskGeometry->SectorsPerTrack, - DiskGeometry->BytesPerSector)); - - Error = RegSetValue(DiskKey, - L"Configuration Data", - REG_FULL_RESOURCE_DESCRIPTOR, - (PCHAR) FullResourceDescriptor, - Size); - MmFreeMemory(FullResourceDescriptor); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, - "RegSetValue(Configuration Data) failed (Error %u)\n", - (int)Error)); - } + /* Get the disk geometry */ + ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY); + if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size)) + { + DiskGeometry->BytesPerSector = ExtGeometry.BytesPerSector; + DiskGeometry->NumberOfCylinders = ExtGeometry.Cylinders; + DiskGeometry->SectorsPerTrack = ExtGeometry.SectorsPerTrack; + DiskGeometry->NumberOfHeads = ExtGeometry.Heads; + } + else if(MachDiskGetDriveGeometry(DriveNumber, &Geometry)) + { + DiskGeometry->BytesPerSector = Geometry.BytesPerSector; + DiskGeometry->NumberOfCylinders = Geometry.Cylinders; + DiskGeometry->SectorsPerTrack = Geometry.Sectors; + DiskGeometry->NumberOfHeads = Geometry.Heads; + } + else + { + DbgPrint((DPRINT_HWDETECT, "Reading disk geometry failed\n")); + return; + } + DbgPrint((DPRINT_HWDETECT, + "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n", + DriveNumber, + DiskGeometry->NumberOfCylinders, + DiskGeometry->NumberOfHeads, + DiskGeometry->SectorsPerTrack, + DiskGeometry->BytesPerSector)); } static VOID -SetHarddiskIdentifier(FRLDRHKEY DiskKey, +SetHarddiskIdentifier(PCHAR Identifier, ULONG DriveNumber) { PMASTER_BOOT_RECORD Mbr; @@ -514,9 +474,7 @@ SetHarddiskIdentifier(FRLDRHKEY DiskKey, ULONG i; ULONG Checksum; ULONG Signature; - WCHAR Identifier[20]; CHAR ArcName[256]; - LONG Error; /* Read the MBR */ if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER)) @@ -547,6 +505,7 @@ SetHarddiskIdentifier(FRLDRHKEY DiskKey, strcpy(reactos_arc_strings[reactos_disk_count], ArcName); reactos_arc_disk_info[reactos_disk_count].ArcName = reactos_arc_strings[reactos_disk_count]; + reactos_arc_disk_info[reactos_disk_count].ValidPartitionTable = TRUE; reactos_disk_count++; /* Convert checksum and signature to identifier string */ @@ -570,152 +529,252 @@ SetHarddiskIdentifier(FRLDRHKEY DiskKey, Identifier[17] = L'-'; Identifier[18] = L'A'; Identifier[19] = 0; - DbgPrint((DPRINT_HWDETECT, "Identifier: %S\n", Identifier)); - - /* Set identifier */ - Error = RegSetValue(DiskKey, - L"Identifier", - REG_SZ, - (PCHAR)Identifier, - sizeof(Identifier)); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, - "RegSetValue(Identifier) failed (Error %u)\n", - (int)Error)); - } + DbgPrint((DPRINT_HWDETECT, "Identifier: %s\n", Identifier)); } -static VOID +static PCONFIGURATION_COMPONENT_DATA DetectBiosDisks(FRLDRHKEY SystemKey, - FRLDRHKEY BusKey) + FRLDRHKEY BusKey, + PCONFIGURATION_COMPONENT_DATA ComponentRoot, + PCONFIGURATION_COMPONENT_DATA PreviousComponent, + BOOLEAN NextChild) { - PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; - PCM_INT13_DRIVE_PARAMETER Int13Drives; - GEOMETRY Geometry; - WCHAR Buffer[80]; - FRLDRHKEY DiskKey; - ULONG DiskCount; - ULONG Size; - ULONG i; - LONG Error; - BOOLEAN Changed; + PCM_INT13_DRIVE_PARAMETER Int13Drives; + PCM_PARTIAL_RESOURCE_LIST ResourceList; + PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor; + PCONFIGURATION_COMPONENT_DATA DiskComponentData, DiskPrevious; + PCONFIGURATION_COMPONENT DiskComponent; + BOOLEAN DisksNextChild; + PVOID ConfigurationData; + USHORT ConfigurationDataLength; + PVOID DeviceData; + USHORT DeviceDataSize; + GEOMETRY Geometry; + ULONG DiskCount; + ULONG Size; + ULONG i; + BOOLEAN Changed; - /* Count the number of visible drives */ - DiskReportError(FALSE); - DiskCount = 0; + /* Count the number of visible drives */ + DiskReportError(FALSE); + DiskCount = 0; - /* There are some really broken BIOSes out there. There are even BIOSes - * that happily report success when you ask them to read from non-existent - * harddisks. So, we set the buffer to known contents first, then try to - * read. If the BIOS reports success but the buffer contents haven't - * changed then we fail anyway */ - memset((PVOID) DISKREADBUFFER, 0xcd, 512); - while (MachDiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, (PVOID)DISKREADBUFFER)) - { - Changed = FALSE; - for (i = 0; ! Changed && i < 512; i++) - { - Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd; - } - if (! Changed) - { - DbgPrint((DPRINT_HWDETECT, "BIOS reports success for disk %d but data didn't change\n", - (int)DiskCount)); - break; - } - DiskCount++; - memset((PVOID) DISKREADBUFFER, 0xcd, 512); - } - DiskReportError(TRUE); - DbgPrint((DPRINT_HWDETECT, "BIOS reports %d harddisk%s\n", - (int)DiskCount, (DiskCount == 1) ? "": "s")); - - /* Allocate resource descriptor */ - Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + - sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount; - FullResourceDescriptor = MmAllocateMemory(Size); - if (FullResourceDescriptor == NULL) - { - DbgPrint((DPRINT_HWDETECT, - "Failed to allocate resource descriptor\n")); - return; - } - - /* Initialize resource descriptor */ - memset(FullResourceDescriptor, 0, Size); - FullResourceDescriptor->InterfaceType = InterfaceTypeUndefined; - FullResourceDescriptor->BusNumber = -1; - FullResourceDescriptor->PartialResourceList.Version = 1; - FullResourceDescriptor->PartialResourceList.Revision = 1; - FullResourceDescriptor->PartialResourceList.Count = 1; - FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Type = - CmResourceTypeDeviceSpecific; -// FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].ShareDisposition = -// FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Flags = - FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize = - sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount; - - /* Get harddisk Int13 geometry data */ - Int13Drives = (PVOID)(((ULONG_PTR)FullResourceDescriptor) + sizeof(CM_FULL_RESOURCE_DESCRIPTOR)); - for (i = 0; i < DiskCount; i++) - { - if (MachDiskGetDriveGeometry(0x80 + i, &Geometry)) + /* There are some really broken BIOSes out there. There are even BIOSes + * that happily report success when you ask them to read from non-existent + * harddisks. So, we set the buffer to known contents first, then try to + * read. If the BIOS reports success but the buffer contents haven't + * changed then we fail anyway */ + memset((PVOID) DISKREADBUFFER, 0xcd, 512); + while (MachDiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, (PVOID)DISKREADBUFFER)) { - Int13Drives[i].DriveSelect = 0x80 + i; - Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1; - Int13Drives[i].SectorsPerTrack = Geometry.Sectors; - Int13Drives[i].MaxHeads = Geometry.Heads - 1; - Int13Drives[i].NumberDrives = DiskCount; - - DbgPrint((DPRINT_HWDETECT, - "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n", - 0x80 + i, - Geometry.Cylinders - 1, - Geometry.Heads -1, - Geometry.Sectors, - Geometry.BytesPerSector)); + Changed = FALSE; + for (i = 0; ! Changed && i < 512; i++) + { + Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd; + } + if (! Changed) + { + DbgPrint((DPRINT_HWDETECT, "BIOS reports success for disk %d but data didn't change\n", + (int)DiskCount)); + break; + } + DiskCount++; + memset((PVOID) DISKREADBUFFER, 0xcd, 512); } - } + DiskReportError(TRUE); + DbgPrint((DPRINT_HWDETECT, "BIOS reports %d harddisk%s\n", + (int)DiskCount, (DiskCount == 1) ? "": "s")); - /* Set 'Configuration Data' value */ - Error = RegSetValue(SystemKey, - L"Configuration Data", - REG_FULL_RESOURCE_DESCRIPTOR, - (PCHAR) FullResourceDescriptor, - Size); - MmFreeMemory(FullResourceDescriptor); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, - "RegSetValue(Configuration Data) failed (Error %u)\n", - (int)Error)); - return; - } + /* Create DiskController */ + DiskComponentData = (PCONFIGURATION_COMPONENT_DATA)MmAllocateMemory(sizeof(CONFIGURATION_COMPONENT_DATA)); + RtlZeroMemory(DiskComponentData, sizeof(CONFIGURATION_COMPONENT_DATA)); - /* Create and fill subkey for each harddisk */ - for (i = 0; i < DiskCount; i++) - { - /* Create disk key */ - swprintf (Buffer, - L"DiskController\\0\\DiskPeripheral\\%u", - i); + DiskComponent = &DiskComponentData->ComponentEntry; + RtlZeroMemory(DiskComponent, sizeof(CONFIGURATION_COMPONENT)); - Error = RegCreateKey(BusKey, - Buffer, - &DiskKey); - if (Error != ERROR_SUCCESS) + DiskComponent->Class = ControllerClass; + DiskComponent->Type = DiskController; + DiskComponent->AffinityMask = 0xFFFFFFFF; + DiskComponent->Flags = 64; // Taken from Windows XP registry + + /* Fill DiskController resources descriptor, which consists of: + Partial Resource List + 3 Partial Resource Descriptors (Dma, Irq and Port) */ + DiskComponentData->ConfigurationData = MmAllocateMemory(sizeof(CM_PARTIAL_RESOURCE_LIST) + + 2*sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); + RtlZeroMemory(DiskComponentData->ConfigurationData, sizeof(CM_PARTIAL_RESOURCE_LIST) + + 2*sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); + ResourceList = (PCM_PARTIAL_RESOURCE_LIST)DiskComponentData->ConfigurationData; + ResourceList->Count = 3; // DMA + Interrupt + Port + + /* DMA */ + ResourceList->PartialDescriptors[0].Type = CmResourceTypeDma; + ResourceList->PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined; + ResourceList->PartialDescriptors[0].u.Dma.Channel = 2; // default channel is 2, at least on WinXP + + /* Interrupt */ + ResourceList->PartialDescriptors[1].Type = CmResourceTypeInterrupt; + ResourceList->PartialDescriptors[1].ShareDisposition = CmResourceShareUndetermined; + ResourceList->PartialDescriptors[1].Flags = CM_RESOURCE_INTERRUPT_LATCHED; + ResourceList->PartialDescriptors[1].u.Interrupt.Level = 6; + ResourceList->PartialDescriptors[1].u.Interrupt.Vector = 6; + ResourceList->PartialDescriptors[1].u.Interrupt.Affinity = 0xFFFFFFFF; + + /* Port */ + ResourceList->PartialDescriptors[2].Type = CmResourceTypePort; + ResourceList->PartialDescriptors[2].ShareDisposition = CmResourceShareDeviceExclusive; + ResourceList->PartialDescriptors[2].Flags = CM_RESOURCE_PORT_IO; + ResourceList->PartialDescriptors[2].u.Port.Start.QuadPart = 0x3F0LL; + ResourceList->PartialDescriptors[2].u.Port.Length = 8; + + /* Add DiskController to the parent/sibling */ + if (NextChild) { - DbgPrint((DPRINT_HWDETECT, "Failed to create drive key\n")); - continue; + PreviousComponent->Child = DiskComponentData; + DiskComponentData->Parent = PreviousComponent; + } + else + { + PreviousComponent->Sibling = DiskComponentData; + DiskComponentData->Parent = PreviousComponent->Parent; } - DbgPrint((DPRINT_HWDETECT, "Created key: %S\n", Buffer)); - /* Set disk values */ - SetHarddiskConfigurationData(DiskKey, 0x80 + i); - SetHarddiskIdentifier(DiskKey, 0x80 + i); - } + /* Get harddisk Int13 geometry data */ + Int13Drives = MmAllocateMemory(sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount); + memset(Int13Drives, 0, sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount); + + for (i = 0; i < DiskCount; i++) + { + if (MachDiskGetDriveGeometry(0x80 + i, &Geometry)) + { + Int13Drives[i].DriveSelect = 0x80 + i; + Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1; + Int13Drives[i].SectorsPerTrack = Geometry.Sectors; + Int13Drives[i].MaxHeads = Geometry.Heads - 1; + Int13Drives[i].NumberDrives = DiskCount; + + DbgPrint((DPRINT_HWDETECT, + "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n", + 0x80 + i, + Geometry.Cylinders - 1, + Geometry.Heads -1, + Geometry.Sectors, + Geometry.BytesPerSector)); + } + } + + /* Add disks as childs of Disk Controller */ + DisksNextChild = TRUE; + DiskPrevious = DiskComponentData; + + for (i = 0; i < DiskCount; i++) + { + PCONFIGURATION_COMPONENT_DATA DiskPeripheralData; + PCONFIGURATION_COMPONENT DiskPeripheralEntry; + PVOID DeviceSpecific; + + /* Create DiskPeripheral */ + DiskPeripheralData = (PCONFIGURATION_COMPONENT_DATA)MmAllocateMemory(sizeof(CONFIGURATION_COMPONENT_DATA)); + RtlZeroMemory(DiskPeripheralData, sizeof(CONFIGURATION_COMPONENT_DATA)); + + DiskPeripheralEntry = &DiskPeripheralData->ComponentEntry; + RtlZeroMemory(DiskPeripheralEntry, sizeof(CONFIGURATION_COMPONENT)); + + DiskPeripheralEntry->Class = PeripheralClass; + DiskPeripheralEntry->Type = DiskPeripheral; + DiskPeripheralEntry->AffinityMask = 0xFFFFFFFF; + DiskPeripheralEntry->Key = i; + DiskPeripheralEntry->Flags = 60; // Taken from Windows XP registry + //DiskPeripheralEntry->Identifier + DiskPeripheralEntry->Identifier = MmAllocateMemory(40); + SetHarddiskIdentifier((PCHAR)DiskPeripheralEntry->Identifier, 0x80 + i); + DiskPeripheralEntry->IdentifierLength = strlen(DiskPeripheralEntry->Identifier); + DiskPeripheralEntry->Identifier = PaToVa(DiskPeripheralEntry->Identifier); + + /* Fill DiskPeripheral resources descriptor, which consists of: + Partial resource list + 1 resource descriptor having device data + in CM_DISK_GEOMETRY_DEVICE_DATA format */ + Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + sizeof(CM_DISK_GEOMETRY_DEVICE_DATA); + DiskPeripheralData->ConfigurationData = MmAllocateMemory(Size); + RtlZeroMemory(DiskPeripheralData->ConfigurationData, Size); + ResourceList = (PCM_PARTIAL_RESOURCE_LIST)DiskPeripheralData->ConfigurationData; + ResourceList->Count = 1; + + /* Device specific data */ + ResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific; + ResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize = sizeof(CM_DISK_GEOMETRY_DEVICE_DATA); + + DeviceSpecific = (PVOID)((ULONG_PTR)DiskPeripheralData->ConfigurationData + sizeof(CM_PARTIAL_RESOURCE_LIST)); + + /* Set disk values */ + SetHarddiskConfigurationData((PCM_DISK_GEOMETRY_DEVICE_DATA)DeviceSpecific, 0x80 + i); + + /* Add DiskController to the parent/sibling */ + if (DisksNextChild) + { + DiskPrevious->Child = DiskPeripheralData; + DiskPeripheralData->Parent = DiskPrevious; + DisksNextChild = FALSE; // all other will be siblings + } + else + { + DiskPrevious->Sibling = DiskPeripheralData; + DiskPeripheralData->Parent = DiskPrevious->Parent; + } + + /* Store just created disk peripheral as previous entry */ + DiskPrevious = DiskPeripheralData; + } + + /* Create configuration data for disks */ + /* Size is 1 resource list containing 2 resource descriptors, each one containing its own device data */ + ConfigurationData = MmAllocateMemory(sizeof(CM_PARTIAL_RESOURCE_LIST) + + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) + DiskCount*sizeof(CM_INT13_DRIVE_PARAMETER) + 0); + + DeviceDataSize = DiskCount*sizeof(CM_INT13_DRIVE_PARAMETER); + + /* Set up resource list*/ + ResourceList = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationData; + ResourceList->Version = 0; + ResourceList->Revision = 0; + ResourceList->Count = 2; + ResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific; + ResourceList->PartialDescriptors[0].Flags = 0; + ResourceList->PartialDescriptors[0].ShareDisposition = 0; + ResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize = DeviceDataSize; + ResourceList->PartialDescriptors[0].u.DeviceSpecificData.Reserved1 = 0; + ResourceList->PartialDescriptors[0].u.DeviceSpecificData.Reserved2 = 0; + + /* Copy disk's device data */ + DeviceData = (PVOID)((ULONG_PTR)ResourceList + sizeof(CM_PARTIAL_RESOURCE_LIST)); + memcpy(DeviceData, (PVOID)Int13Drives, DeviceDataSize); + + MmFreeMemory(Int13Drives); + + /* Now fill the 2nd partial resource descriptor */ + ResourceDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)((ULONG_PTR)ResourceList + + sizeof(CM_PARTIAL_RESOURCE_LIST) + DeviceDataSize); + + /* We don't provide any info yet for the 2nd partial resource descriptor */ + DeviceDataSize = 0; + + ResourceDescriptor->Type = CmResourceTypeDeviceSpecific; + ResourceDescriptor->Flags = 0; + ResourceDescriptor->ShareDisposition = 0; + ResourceDescriptor->u.DeviceSpecificData.DataSize = DeviceDataSize; + ResourceDescriptor->u.DeviceSpecificData.Reserved1 = 0; + ResourceDescriptor->u.DeviceSpecificData.Reserved2 = 0; + + ConfigurationDataLength = sizeof(CM_PARTIAL_RESOURCE_LIST) + + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) + DiskCount*sizeof(CM_INT13_DRIVE_PARAMETER) + 0; + + /* Store this information in SystemClass */ + ComponentRoot->ComponentEntry.ConfigurationDataLength = ConfigurationDataLength; + ComponentRoot->ConfigurationData = ConfigurationData; + + + /* Return pointer to the disk controller */ + return DiskComponentData; } @@ -1631,6 +1690,7 @@ DetectKeyboardDevice(VOID) if ((Status & 0x01) != 0x01) { /* PC/XT keyboard or no keyboard */ + DPRINT1("PC/XT keyboard or no keyboard found\n"); return FALSE; } @@ -1638,6 +1698,7 @@ DetectKeyboardDevice(VOID) if (Scancode != 0xFA) { /* No ACK received */ + DPRINT1("No ACK received\n"); return FALSE; } @@ -1653,6 +1714,7 @@ DetectKeyboardDevice(VOID) if (Scancode != 0xAB) { /* No 0xAB received */ + DPRINT1("No 0xAB received\n"); return FALSE; } @@ -1661,6 +1723,7 @@ DetectKeyboardDevice(VOID) if ((Status & 0x01) != 0x01) { /* No byte in buffer */ + DPRINT1("No byte in buffer\n"); return FALSE; } @@ -1668,193 +1731,164 @@ DetectKeyboardDevice(VOID) if (Scancode != 0x41) { /* No 0x41 received */ + DPRINT1("No 0x41 received\n"); return FALSE; } /* Found MF-II keyboard */ + DPRINT1("Found MF-II keyboard\n"); return TRUE; } +static USHORT +KeyboardGetShiftFlags() +{ + REGS RegsIn; + REGS RegsOut; + + /* Uses Int 16h / AH=02h */ + + RegsIn.b.ah = 0x02; /* Subfunction 02h */ + RegsIn.b.al = 0x00; + + Int386(0x16, &RegsIn, &RegsOut); + + /* Return ax */ + if (INT386_SUCCESS(RegsOut)) + return RegsOut.w.ax; + else + return 0; +} static VOID -DetectKeyboardPeripheral(FRLDRHKEY ControllerKey) +DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA KeyboardController) { - PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; - PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; - PCM_KEYBOARD_DEVICE_DATA KeyboardData; - FRLDRHKEY PeripheralKey; - ULONG Size; - LONG Error; + PCM_PARTIAL_RESOURCE_LIST ResourceList; + PCM_KEYBOARD_DEVICE_DATA KeyboardData; + ULONG Size; - /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2 */ - if (TRUE || DetectKeyboardDevice()) - { - /* Create controller key */ - Error = RegCreateKey(ControllerKey, - L"KeyboardPeripheral\\0", - &PeripheralKey); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "Failed to create peripheral key\n")); - return; - } - DbgPrint((DPRINT_HWDETECT, "Created key: KeyboardPeripheral\\0\n")); + /* HACK: Keyboard detection under qemu doesn't work! */ + if (TRUE || DetectKeyboardDevice()) + { + PCONFIGURATION_COMPONENT_DATA KeyboardComponentData; + PCONFIGURATION_COMPONENT KeyboardEntry; - /* Set 'ComponentInformation' value */ - SetComponentInformation(ControllerKey, - 0x28, - 0, - 0xFFFFFFFF); + /* Create DiskPeripheral */ + KeyboardComponentData = (PCONFIGURATION_COMPONENT_DATA)MmAllocateMemory(sizeof(CONFIGURATION_COMPONENT_DATA)); + RtlZeroMemory(KeyboardComponentData, sizeof(CONFIGURATION_COMPONENT_DATA)); - /* Set 'Configuration Data' value */ - Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + - sizeof(CM_KEYBOARD_DEVICE_DATA); - FullResourceDescriptor = MmAllocateMemory(Size); - if (FullResourceDescriptor == NULL) - { - DbgPrint((DPRINT_HWDETECT, - "Failed to allocate resource descriptor\n")); - return; - } + KeyboardEntry = &KeyboardComponentData->ComponentEntry; + RtlZeroMemory(KeyboardEntry, sizeof(CONFIGURATION_COMPONENT)); - /* Initialize resource descriptor */ - memset(FullResourceDescriptor, 0, Size); - FullResourceDescriptor->InterfaceType = Isa; - FullResourceDescriptor->BusNumber = 0; - FullResourceDescriptor->PartialResourceList.Version = 1; - FullResourceDescriptor->PartialResourceList.Revision = 1; - FullResourceDescriptor->PartialResourceList.Count = 1; + KeyboardEntry->Class = PeripheralClass; + KeyboardEntry->Type = KeyboardPeripheral; + KeyboardEntry->AffinityMask = 0xFFFFFFFF; + KeyboardEntry->Flags = 0x28; + KeyboardEntry->Identifier = MmAllocateMemory(14); + strcpy(KeyboardEntry->Identifier, "PCAT_ENHANCED"); + KeyboardEntry->IdentifierLength = strlen(KeyboardEntry->Identifier); + KeyboardEntry->Identifier = PaToVa(KeyboardEntry->Identifier); - PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0]; - PartialDescriptor->Type = CmResourceTypeDeviceSpecific; - PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; - PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_KEYBOARD_DEVICE_DATA); + /* Fill KeyboardPeripheral resources descriptor, which consists of: + Partial resource list + 1 resource descriptor having device data + in CM_KEYBOARD_DEVICE_DATA format */ + Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + sizeof(CM_KEYBOARD_DEVICE_DATA); + KeyboardComponentData->ConfigurationData = MmAllocateMemory(Size); + RtlZeroMemory(KeyboardComponentData->ConfigurationData, Size); + ResourceList = (PCM_PARTIAL_RESOURCE_LIST)KeyboardComponentData->ConfigurationData; + ResourceList->Count = 1; - KeyboardData = (PCM_KEYBOARD_DEVICE_DATA)(PartialDescriptor + 1); - KeyboardData->Version = 1; - KeyboardData->Revision = 1; - KeyboardData->Type = 4; - KeyboardData->Subtype = 0; - KeyboardData->KeyboardFlags = 0x20; + /* Device specific data */ + ResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific; + ResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize = sizeof(PCM_KEYBOARD_DEVICE_DATA); - /* Set 'Configuration Data' value */ - Error = RegSetValue(PeripheralKey, - L"Configuration Data", - REG_FULL_RESOURCE_DESCRIPTOR, - (PCHAR)FullResourceDescriptor, - Size); - MmFreeMemory(FullResourceDescriptor); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, - "RegSetValue(Configuration Data) failed (Error %u)\n", - (int)Error)); - } + KeyboardData = (PCM_KEYBOARD_DEVICE_DATA)((ULONG_PTR)KeyboardComponentData->ConfigurationData + sizeof(CM_PARTIAL_RESOURCE_LIST)); - /* Set 'Identifier' value */ - Error = RegSetValue(PeripheralKey, - L"Identifier", - REG_SZ, - (PCHAR)L"PCAT_ENHANCED", - 14 * sizeof(WCHAR)); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, - "RegSetValue() failed (Error %u)\n", - (int)Error)); - } - } + /* Set device-specific data */ + KeyboardData->Type = 4; + KeyboardData->Subtype = 0; + KeyboardData->KeyboardFlags = KeyboardGetShiftFlags(); + + /* Add Keyboard peripheral to the parent */ + KeyboardController->Child = KeyboardComponentData; + KeyboardComponentData->Parent = KeyboardController; + } } -static VOID -DetectKeyboardController(FRLDRHKEY BusKey) +static +PCONFIGURATION_COMPONENT_DATA +DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA ParentComponent, + BOOLEAN NextChild) { - PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; - PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; - FRLDRHKEY ControllerKey; - ULONG Size; - LONG Error; + PCONFIGURATION_COMPONENT_DATA ControllerComponent; + PCONFIGURATION_COMPONENT ControllerEntry; + PCM_PARTIAL_RESOURCE_LIST ResourceList; - /* Create controller key */ - Error = RegCreateKey(BusKey, - L"KeyboardController\\0", - &ControllerKey); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "Failed to create controller key\n")); - return; - } - DbgPrint((DPRINT_HWDETECT, "Created key: KeyboardController\\0\n")); + return ParentComponent; - /* Set 'ComponentInformation' value */ - SetComponentInformation(ControllerKey, - 0x28, - 0, - 0xFFFFFFFF); + /* Create controller key */ + ControllerComponent = (PCONFIGURATION_COMPONENT_DATA)MmAllocateMemory(sizeof(CONFIGURATION_COMPONENT_DATA)); + RtlZeroMemory(ControllerComponent, sizeof(CONFIGURATION_COMPONENT_DATA)); - /* Set 'Configuration Data' value */ - Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + - 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); - FullResourceDescriptor = MmAllocateMemory(Size); - if (FullResourceDescriptor == NULL) - { - DbgPrint((DPRINT_HWDETECT, - "Failed to allocate resource descriptor\n")); - return; - } + ControllerEntry = &ControllerComponent->ComponentEntry; + RtlZeroMemory(ControllerEntry, sizeof(CONFIGURATION_COMPONENT)); - /* Initialize resource descriptor */ - memset(FullResourceDescriptor, 0, Size); - FullResourceDescriptor->InterfaceType = Isa; - FullResourceDescriptor->BusNumber = 0; - FullResourceDescriptor->PartialResourceList.Version = 1; - FullResourceDescriptor->PartialResourceList.Revision = 1; - FullResourceDescriptor->PartialResourceList.Count = 3; + ControllerEntry->Class = ControllerClass; + ControllerEntry->Type = KeyboardController; + ControllerEntry->AffinityMask = 0xFFFFFFFF; + ControllerEntry->Flags = 0x28; - /* Set Interrupt */ - PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0]; - PartialDescriptor->Type = CmResourceTypeInterrupt; - PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; - PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; - PartialDescriptor->u.Interrupt.Level = 0; - PartialDescriptor->u.Interrupt.Vector = 1; - PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF; + /* Fill keyboard controller resources descriptor, which consists of: + Partial Resource List + 2 Partial Resource Descriptors (Irq and 2 Ports) */ + ControllerComponent->ConfigurationData = MmAllocateMemory(sizeof(CM_PARTIAL_RESOURCE_LIST) + + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); + RtlZeroMemory(ControllerComponent->ConfigurationData, sizeof(CM_PARTIAL_RESOURCE_LIST) + + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); + ResourceList = (PCM_PARTIAL_RESOURCE_LIST)ControllerComponent->ConfigurationData; + ResourceList->Count = 2; // Interrupt + Port + Port - /* Set IO Port 0x60 */ - PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[1]; - PartialDescriptor->Type = CmResourceTypePort; - PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; - PartialDescriptor->Flags = CM_RESOURCE_PORT_IO; - PartialDescriptor->u.Port.Start.LowPart = 0x60; - PartialDescriptor->u.Port.Start.HighPart = 0x0; - PartialDescriptor->u.Port.Length = 1; + /* Interrupt */ + ResourceList->PartialDescriptors[0].Type = CmResourceTypeInterrupt; + ResourceList->PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined; + ResourceList->PartialDescriptors[0].Flags = CM_RESOURCE_INTERRUPT_LATCHED; + ResourceList->PartialDescriptors[0].u.Interrupt.Level = 0; + ResourceList->PartialDescriptors[0].u.Interrupt.Vector = 1; + ResourceList->PartialDescriptors[0].u.Interrupt.Affinity = 0xFFFFFFFF; - /* Set IO Port 0x64 */ - PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[2]; - PartialDescriptor->Type = CmResourceTypePort; - PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; - PartialDescriptor->Flags = CM_RESOURCE_PORT_IO; - PartialDescriptor->u.Port.Start.LowPart = 0x64; - PartialDescriptor->u.Port.Start.HighPart = 0x0; - PartialDescriptor->u.Port.Length = 1; + /* Set IO Port 0x60 */ + ResourceList->PartialDescriptors[1].Type = CmResourceTypePort; + ResourceList->PartialDescriptors[1].ShareDisposition = CmResourceShareDeviceExclusive; + ResourceList->PartialDescriptors[1].Flags = CM_RESOURCE_PORT_IO; + ResourceList->PartialDescriptors[1].u.Port.Start.LowPart = 0x60; + ResourceList->PartialDescriptors[1].u.Port.Start.HighPart = 0x0; + ResourceList->PartialDescriptors[1].u.Port.Length = 1; - /* Set 'Configuration Data' value */ - Error = RegSetValue(ControllerKey, - L"Configuration Data", - REG_FULL_RESOURCE_DESCRIPTOR, - (PCHAR)FullResourceDescriptor, - Size); - MmFreeMemory(FullResourceDescriptor); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, - "RegSetValue(Configuration Data) failed (Error %u)\n", - (int)Error)); - return; - } + /* Set IO Port 0x64 */ + ResourceList->PartialDescriptors[2].Type = CmResourceTypePort; + ResourceList->PartialDescriptors[2].ShareDisposition = CmResourceShareDeviceExclusive; + ResourceList->PartialDescriptors[2].Flags = CM_RESOURCE_PORT_IO; + ResourceList->PartialDescriptors[2].u.Port.Start.LowPart = 0x64; + ResourceList->PartialDescriptors[2].u.Port.Start.HighPart = 0x0; + ResourceList->PartialDescriptors[2].u.Port.Length = 1; - DetectKeyboardPeripheral(ControllerKey); + /* Add this keyboard controller to the parent/sibling */ + if (NextChild) + { + ParentComponent->Child = ControllerComponent; + ControllerComponent->Parent = ParentComponent; + } + else + { + ParentComponent->Sibling = ControllerComponent; + ControllerComponent->Parent = ParentComponent->Parent; + } + + /* Detect any keyboard attached to this controller */ + DetectKeyboardPeripheral(ControllerComponent); + + /* Return pointer to the keyboard controller */ + return ControllerComponent; } @@ -2156,9 +2190,16 @@ DetectDisplayController(FRLDRHKEY BusKey) static VOID -DetectIsaBios(FRLDRHKEY SystemKey, ULONG *BusNumber) +DetectIsaBios(FRLDRHKEY SystemKey, + ULONG *BusNumber, + PCONFIGURATION_COMPONENT_DATA ComponentRoot, + PCONFIGURATION_COMPONENT_DATA PreviousComponent, + BOOLEAN NextChild) { PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; + PCONFIGURATION_COMPONENT_DATA IsaAdapter, LastComponent; + PCONFIGURATION_COMPONENT IsaComponent; + PVOID Identifier; WCHAR Buffer[80]; FRLDRHKEY BusKey; ULONG Size; @@ -2231,8 +2272,39 @@ DetectIsaBios(FRLDRHKEY SystemKey, ULONG *BusNumber) return; } + + /* Create adapter component */ + IsaAdapter = MmAllocateMemory(sizeof(CONFIGURATION_COMPONENT_DATA)); + RtlZeroMemory(IsaAdapter, sizeof(CONFIGURATION_COMPONENT_DATA)); + + IsaComponent = &IsaAdapter->ComponentEntry; + RtlZeroMemory(IsaComponent, sizeof(CONFIGURATION_COMPONENT)); + + IsaComponent->Class = AdapterClass; + IsaComponent->Type = MultiFunctionAdapter; + IsaComponent->AffinityMask = 0xFFFFFFFF; + Identifier = MmAllocateMemory(sizeof("ISA")+1); + sprintf(Identifier, "ISA"); + IsaComponent->Identifier = PaToVa(Identifier); + IsaComponent->IdentifierLength = strlen(Identifier)+1; + + if (NextChild) + { + PreviousComponent->Child = IsaAdapter; + IsaAdapter->Parent = PreviousComponent; + } + else + { + PreviousComponent->Sibling = IsaAdapter; + IsaAdapter->Parent = PreviousComponent->Parent; + } + + /* Detect ISA/BIOS devices */ - DetectBiosDisks(SystemKey, BusKey); + + /* DetectBiosDisks writes information both to the root entry and to + its own entries */ + LastComponent = DetectBiosDisks(SystemKey, BusKey, ComponentRoot, IsaAdapter, TRUE); DetectBiosFloppyController(SystemKey, BusKey); @@ -2240,7 +2312,10 @@ DetectIsaBios(FRLDRHKEY SystemKey, ULONG *BusNumber) DetectParallelPorts(BusKey); - DetectKeyboardController(BusKey); + /* Detect keyboard and mouse */ + LastComponent = + DetectKeyboardController(LastComponent, + (IsaAdapter == LastComponent) ? TRUE : FALSE); DetectPS2Mouse(BusKey); @@ -2251,14 +2326,18 @@ DetectIsaBios(FRLDRHKEY SystemKey, ULONG *BusNumber) VOID -PcHwDetect(VOID) +PcHwDetect(PCONFIGURATION_COMPONENT_DATA *ComponentRoot) { FRLDRHKEY SystemKey; ULONG BusNumber = 0; LONG Error; + PCONFIGURATION_COMPONENT Component; + PCONFIGURATION_COMPONENT_DATA LastComponentData; + DbgPrint((DPRINT_HWDETECT, "DetectHardware()\n")); +#if ROS_SPECIFIC /* Create the 'System' key */ Error = RegCreateKey(NULL, L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System", @@ -2268,6 +2347,16 @@ PcHwDetect(VOID) DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); return; } +#endif + + /* Allocate root configuration component */ + *ComponentRoot = MmAllocateMemory(sizeof(CONFIGURATION_COMPONENT_DATA)); + RtlZeroMemory(*ComponentRoot, sizeof(CONFIGURATION_COMPONENT_DATA)); + + /* Create root node - "System" */ + Component = &((*ComponentRoot)->ComponentEntry); + Component->Class = SystemClass; + Component->Type = MaximumType; #if 0 DetectSystemData(); @@ -2275,10 +2364,12 @@ PcHwDetect(VOID) DetectCPUs(SystemKey); /* Detect buses */ - DetectPciBios(SystemKey, &BusNumber); + /* FIXME: Don't forget situation when some buses may be absent! (NextChild = TRUE then) */ + LastComponentData = DetectPciBios(SystemKey, &BusNumber, *ComponentRoot, *ComponentRoot, TRUE); DetectApmBios(SystemKey, &BusNumber); DetectPnpBios(SystemKey, &BusNumber); - DetectIsaBios(SystemKey, &BusNumber); + DetectIsaBios(SystemKey, &BusNumber, *ComponentRoot, LastComponentData, + (LastComponentData == *ComponentRoot) ? TRUE : FALSE); DetectAcpiBios(SystemKey, &BusNumber); DbgPrint((DPRINT_HWDETECT, "DetectHardware() Done\n")); diff --git a/arch/i386/hwpci.c b/arch/i386/hwpci.c index 1046ec1ed6e..dee4d65108b 100644 --- a/arch/i386/hwpci.c +++ b/arch/i386/hwpci.c @@ -56,8 +56,9 @@ typedef struct _PCI_IRQ_ROUTING_TABLE typedef struct _CM_PCI_BUS_DATA { + UCHAR VersionMinor; + UCHAR VersionMajor; UCHAR BusCount; - USHORT PciVersion; UCHAR HardwareMechanism; } __attribute__((packed)) CM_PCI_BUS_DATA, *PCM_PCI_BUS_DATA; @@ -126,8 +127,9 @@ FindPciBios(PCM_PCI_BUS_DATA BusData) DbgPrint((DPRINT_HWDETECT, "CL: %x\n", RegsOut.b.cl)); BusData->BusCount = RegsOut.b.cl + 1; - BusData->PciVersion = RegsOut.w.bx; - BusData->HardwareMechanism = RegsOut.b.cl; + BusData->VersionMajor = RegsOut.b.bh; + BusData->VersionMinor = RegsOut.b.bl; + BusData->HardwareMechanism = RegsOut.b.al; return TRUE; } @@ -225,143 +227,170 @@ DetectPciIrqRoutingTable(FRLDRHKEY BusKey) } -VOID -DetectPciBios(FRLDRHKEY SystemKey, ULONG *BusNumber) +PCONFIGURATION_COMPONENT_DATA +DetectPciBios(FRLDRHKEY SystemKey, + ULONG *BusNumber, + PCONFIGURATION_COMPONENT_DATA ComponentRoot, + PCONFIGURATION_COMPONENT_DATA PreviousComponent, + BOOLEAN NextChild) { - PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; - CM_PCI_BUS_DATA BusData; - WCHAR Buffer[80]; - FRLDRHKEY BiosKey; - ULONG Size; - LONG Error; -#if 0 - FRLDRHKEY BusKey; - ULONG i; - WCHAR szPci[] = L"PCI"; -#endif + PCONFIGURATION_COMPONENT_DATA PciBusComponentData, PreviousBusData; + PCONFIGURATION_COMPONENT PciBusComponent; + PVOID Identifier; + PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; + CM_PCI_BUS_DATA BusData; + WCHAR Buffer[80]; + FRLDRHKEY BiosKey; + ULONG Size; + LONG Error; + ULONG i; + BOOLEAN NextComponentChild; - /* Report the PCI BIOS */ - if (FindPciBios(&BusData)) - { - /* Create new bus key */ - swprintf(Buffer, - L"MultifunctionAdapter\\%u", *BusNumber); - Error = RegCreateKey(SystemKey, - Buffer, - &BiosKey); - if (Error != ERROR_SUCCESS) + /* Return Previous component in case no PCI buses are detected */ + PreviousBusData = PreviousComponent; + NextComponentChild = NextChild; + + /* Report the PCI BIOS */ + if (FindPciBios(&BusData)) { - DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); - return; + /* Create new bus key */ + swprintf(Buffer, + L"MultifunctionAdapter\\%u", *BusNumber); + Error = RegCreateKey(SystemKey, + Buffer, + &BiosKey); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); + //return NULL; + } + + /* Set 'Component Information' */ + SetComponentInformation(BiosKey, + 0x0, + 0x0, + 0xFFFFFFFF); + + /* Increment bus number */ + (*BusNumber)++; + + /* Set 'Identifier' value */ + Error = RegSetValue(BiosKey, + L"Identifier", + REG_SZ, + (PCHAR)L"PCI BIOS", + 9 * sizeof(WCHAR)); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); + //return NULL; + } + + /* Set 'Configuration Data' value */ + Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR); + FullResourceDescriptor = MmAllocateMemory(Size); + if (FullResourceDescriptor == NULL) + { + DbgPrint((DPRINT_HWDETECT, + "Failed to allocate resource descriptor\n")); + //return NULL; + } + + /* Initialize resource descriptor */ + memset(FullResourceDescriptor, 0, Size); + FullResourceDescriptor->InterfaceType = PCIBus; + FullResourceDescriptor->BusNumber = 0; + FullResourceDescriptor->PartialResourceList.Version = 1; + FullResourceDescriptor->PartialResourceList.Revision = 1; + FullResourceDescriptor->PartialResourceList.Count = 1; + FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeBusNumber; + FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareDeviceExclusive; + FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.BusNumber.Start = 0; + FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.BusNumber.Length = 1; + + /* Set 'Configuration Data' value */ + Error = RegSetValue(BiosKey, + L"Configuration Data", + REG_FULL_RESOURCE_DESCRIPTOR, + (PCHAR) FullResourceDescriptor, + Size); + MmFreeMemory(FullResourceDescriptor); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, + "RegSetValue(Configuration Data) failed (Error %u)\n", + (int)Error)); + //return NULL; + } + + DetectPciIrqRoutingTable(BiosKey); + + /* Attach to the component we've got -- as child */ + PreviousBusData = PreviousComponent; + NextComponentChild = NextChild; + + /* Report PCI buses */ + for (i = 0; i < (ULONG)BusData.BusCount; i++) + { + /* Create data component */ + PciBusComponentData = MmAllocateMemory(sizeof(CONFIGURATION_COMPONENT_DATA)); + RtlZeroMemory(PciBusComponentData, sizeof(CONFIGURATION_COMPONENT_DATA)); + + /* Save a pointer to the ComponentEntry */ + PciBusComponent = &PciBusComponentData->ComponentEntry; + + /* Fill ComponentEntry */ + PciBusComponent->Class = AdapterClass; + PciBusComponent->Type = MultiFunctionAdapter; + PciBusComponent->AffinityMask = 0xFFFFFFFF; + Identifier = MmAllocateMemory(sizeof("PCI")+1); + sprintf(Identifier, "PCI"); + PciBusComponent->Identifier = PaToVa(Identifier); + PciBusComponent->IdentifierLength = strlen(Identifier)+1; + + /* We have to treat first PCI bus's data differently */ + if (i == 0) + { + PCM_PARTIAL_RESOURCE_LIST ResourceList; + PVOID DeviceSpecific; + + Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + sizeof(CM_PCI_BUS_DATA); + PciBusComponent->ConfigurationDataLength = Size; + PciBusComponentData->ConfigurationData = MmAllocateMemory(Size); + RtlZeroMemory(PciBusComponentData->ConfigurationData, Size); + + ResourceList = (PCM_PARTIAL_RESOURCE_LIST)PciBusComponentData->ConfigurationData; + ResourceList->Count = 1; + ResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific; + ResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize = sizeof(CM_PCI_BUS_DATA); + + /* Fill actual data */ + DeviceSpecific = (PVOID)((ULONG_PTR)PciBusComponentData->ConfigurationData + sizeof(CM_PARTIAL_RESOURCE_LIST)); + RtlCopyMemory(DeviceSpecific, (PVOID)&BusData, sizeof(CM_PCI_BUS_DATA)); + } + + if (NextComponentChild) + { + PreviousBusData->Child = PciBusComponentData; + PciBusComponentData->Parent = PreviousBusData; + + NextComponentChild = FALSE; + } + else + { + PreviousBusData->Sibling = PciBusComponentData; + PciBusComponentData->Parent = PreviousBusData->Parent; + } + + PreviousBusData = PciBusComponentData; + + /* Increment bus number */ + (*BusNumber)++; + } + } - /* Set 'Component Information' */ - SetComponentInformation(BiosKey, - 0x0, - 0x0, - 0xFFFFFFFF); - - /* Increment bus number */ - (*BusNumber)++; - - /* Set 'Identifier' value */ - Error = RegSetValue(BiosKey, - L"Identifier", - REG_SZ, - (PCHAR)L"PCI BIOS", - 9 * sizeof(WCHAR)); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); - return; - } - - /* Set 'Configuration Data' value */ - Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR); - FullResourceDescriptor = MmAllocateMemory(Size); - if (FullResourceDescriptor == NULL) - { - DbgPrint((DPRINT_HWDETECT, - "Failed to allocate resource descriptor\n")); - return; - } - - /* Initialize resource descriptor */ - memset(FullResourceDescriptor, 0, Size); - FullResourceDescriptor->InterfaceType = PCIBus; - FullResourceDescriptor->BusNumber = 0; - FullResourceDescriptor->PartialResourceList.Version = 1; - FullResourceDescriptor->PartialResourceList.Revision = 1; - FullResourceDescriptor->PartialResourceList.Count = 1; - FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeBusNumber; - FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareDeviceExclusive; - FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.BusNumber.Start = 0; - FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.BusNumber.Length = 1; - - /* Set 'Configuration Data' value */ - Error = RegSetValue(BiosKey, - L"Configuration Data", - REG_FULL_RESOURCE_DESCRIPTOR, - (PCHAR) FullResourceDescriptor, - Size); - MmFreeMemory(FullResourceDescriptor); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, - "RegSetValue(Configuration Data) failed (Error %u)\n", - (int)Error)); - return; - } - - DetectPciIrqRoutingTable(BiosKey); - -#if 0 - /* - * FIXME: - * Enabling this piece of code will corrupt the boot sequence! - * This is probably caused by a bug in the registry code! - */ - - /* Report PCI buses */ - for (i = 0; i < (ULONG)BusData.BusCount; i++) - { - swprintf(Buffer, - L"MultifunctionAdapter\\%u", *BusNumber); - Error = RegCreateKey(SystemKey, - Buffer, - &BusKey); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); - printf("RegCreateKey() failed (Error %u)\n", (int)Error); - return; - } - - /* Set 'Component Information' */ - SetComponentInformation(BusKey, - 0x0, - 0x0, - 0xFFFFFFFF); - - /* Increment bus number */ - (*BusNumber)++; - - - /* Set 'Identifier' value */ - Error = RegSetValue(BusKey, - L"Identifier", - REG_SZ, - (PCSTR)szPci, - sizeof(szPci)); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); - return; - } - } -#endif - - } + return PreviousBusData; } /* EOF */ diff --git a/arch/i386/i386idt.S b/arch/i386/i386idt.S index 7fc46fa9ff0..0e2fad8c140 100644 --- a/arch/i386/i386idt.S +++ b/arch/i386/i386idt.S @@ -27,93 +27,93 @@ .p2align 2 /* force 4-byte alignment */ EXTERN(i386idt) /* Exception 0 - Divide By Zero */ - .word i386DivideByZero /* Offset 0 - 15 */ + .word _i386DivideByZero /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Flags, Zero Byte */ + .word 0x8f00 /* Flags, Zero Byte */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 1 - Debug Exception */ - .word i386DebugException /* Offset 0 - 15 */ + .word _i386DebugException /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 2 - NMI */ - .word i386NMIException /* Offset 0 - 15 */ + .word _i386NMIException /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 3 - Breakpoint (INT 3) */ - .word i386Breakpoint /* Offset 0 - 15 */ + .word _i386Breakpoint /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 4 - Overflow (INTO with EFLAGS[OF] set) */ - .word i386Overflow /* Offset 0 - 15 */ + .word _i386Overflow /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 5 - Bound Exception */ - .word i386BoundException /* Offset 0 - 15 */ + .word _i386BoundException /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 6 - Invalid Opcode */ - .word i386InvalidOpcode /* Offset 0 - 15 */ + .word _i386InvalidOpcode /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 7 - FPU Not Available */ - .word i386FPUNotAvailable /* Offset 0 - 15 */ + .word _i386FPUNotAvailable /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 8 - Double Fault */ - .word i386DoubleFault /* Offset 0 - 15 */ + .word _i386DoubleFault /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 9 - Coprocessor Segment Overrun */ - .word i386CoprocessorSegment /* Offset 0 - 15 */ + .word _i386CoprocessorSegment /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 10 (0x0A) - Invalid TSS */ - .word i386InvalidTSS /* Offset 0 - 15 */ + .word _i386InvalidTSS /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 11 (0x0B) - Segment Not Present */ - .word i386SegmentNotPresent /* Offset 0 - 15 */ + .word _i386SegmentNotPresent /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 12 (0x0C) - Stack Exception */ - .word i386StackException /* Offset 0 - 15 */ + .word _i386StackException /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 13 (0x0D) - General Protection Fault */ - .word i386GeneralProtectionFault /* Offset 0 - 15 */ + .word _i386GeneralProtectionFault /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 14 (0x0E) - Page Fault */ - .word i386PageFault /* Offset 0 - 15 */ + .word _i386PageFault /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 15 (0x0F) - Reserved */ @@ -123,21 +123,21 @@ EXTERN(i386idt) .word 0x0000 /* Offset 16 - 31 */ /* Exception 16 (0x10) - Coprocessor Error */ - .word i386CoprocessorError /* Offset 0 - 15 */ + .word _i386CoprocessorError /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 17 (0x11) - Alignment Check */ - .word i386AlignmentCheck /* Offset 0 - 15 */ + .word _i386AlignmentCheck /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 18 (0x12) - Machine Check */ - .word i386MachineCheck /* Offset 0 - 15 */ + .word _i386MachineCheck /* Offset 0 - 15 */ .word 0x0008 /* Selector */ - .word 0x8e00 /* Zero byte, flags */ + .word 0x8f00 /* Zero byte, flags */ .word 0x0000 /* Offset 16 - 31 */ /* Exception 19 (0x13) - Reserved */ diff --git a/arch/i386/i386trap.S b/arch/i386/i386trap.S index 4a367311677..b17a2a090f8 100644 --- a/arch/i386/i386trap.S +++ b/arch/i386/i386trap.S @@ -591,63 +591,63 @@ i386PrintHexByte1: ret /************************************************************************/ -EXTERN(i386DivideByZero) +EXTERN(_i386DivideByZero) .code32 movl $i386DivideByZeroText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386DebugException) +EXTERN(_i386DebugException) .code32 movl $i386DebugExceptionText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386NMIException) +EXTERN(_i386NMIException) .code32 movl $i386NMIExceptionText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386Breakpoint) +EXTERN(_i386Breakpoint) .code32 movl $i386BreakpointText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386Overflow) +EXTERN(_i386Overflow) .code32 movl $i386OverflowText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386BoundException) +EXTERN(_i386BoundException) .code32 movl $i386BoundExceptionText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386InvalidOpcode) +EXTERN(_i386InvalidOpcode) .code32 movl $i386InvalidOpcodeText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386FPUNotAvailable) +EXTERN(_i386FPUNotAvailable) .code32 movl $i386FPUNotAvailableText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386DoubleFault) +EXTERN(_i386DoubleFault) .code32 popl %eax @@ -657,14 +657,14 @@ EXTERN(i386DoubleFault) jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386CoprocessorSegment) +EXTERN(_i386CoprocessorSegment) .code32 movl $i386CoprocessorSegmentText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386InvalidTSS) +EXTERN(_i386InvalidTSS) .code32 popl %eax @@ -674,7 +674,7 @@ EXTERN(i386InvalidTSS) jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386SegmentNotPresent) +EXTERN(_i386SegmentNotPresent) .code32 popl %eax @@ -684,7 +684,7 @@ EXTERN(i386SegmentNotPresent) jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386StackException) +EXTERN(_i386StackException) .code32 popl %eax @@ -694,7 +694,7 @@ EXTERN(i386StackException) jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386GeneralProtectionFault) +EXTERN(_i386GeneralProtectionFault) .code32 popl %eax @@ -704,7 +704,7 @@ EXTERN(i386GeneralProtectionFault) jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386PageFault) +EXTERN(_i386PageFault) .code32 popl %eax @@ -714,21 +714,21 @@ EXTERN(i386PageFault) jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386CoprocessorError) +EXTERN(_i386CoprocessorError) .code32 movl $i386CoprocessorErrorText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386AlignmentCheck) +EXTERN(_i386AlignmentCheck) .code32 movl $i386AlignmentCheckText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ -EXTERN(i386MachineCheck) +EXTERN(_i386MachineCheck) .code32 movl $i386MachineCheckText,i386ExceptionDescriptionText diff --git a/arch/i386/xboxhw.c b/arch/i386/xboxhw.c index f310a47febf..249e0fa1391 100644 --- a/arch/i386/xboxhw.c +++ b/arch/i386/xboxhw.c @@ -20,7 +20,7 @@ #include VOID -XboxHwDetect(VOID) +XboxHwDetect(PCONFIGURATION_COMPONENT_DATA *ComponentRoot) { } diff --git a/freeldr_arch.rbuild b/freeldr_arch.rbuild index ca61e7448ed..c92eaf3edc6 100644 --- a/freeldr_arch.rbuild +++ b/freeldr_arch.rbuild @@ -6,10 +6,11 @@ cache include - + + -ffreestanding -fno-builtin -fno-inline @@ -56,6 +57,7 @@ --> + -ffreestanding -fno-builtin -fno-inline diff --git a/freeldr_base.rbuild b/freeldr_base.rbuild index fe4cf462b15..b319454a725 100644 --- a/freeldr_base.rbuild +++ b/freeldr_base.rbuild @@ -4,9 +4,9 @@ . include - + -ffreestanding diff --git a/freeldr_base64k.rbuild b/freeldr_base64k.rbuild index d9e20fd17aa..4e3975bc7c9 100644 --- a/freeldr_base64k.rbuild +++ b/freeldr_base64k.rbuild @@ -6,6 +6,7 @@ --> + -ffreestanding -fno-builtin -fno-inline diff --git a/freeldr_main.rbuild b/freeldr_main.rbuild index a698373ef6e..d6e0c3181f5 100644 --- a/freeldr_main.rbuild +++ b/freeldr_main.rbuild @@ -2,10 +2,11 @@ include include - + + -ffreestanding -fno-builtin -fno-inline diff --git a/include/arch/i386/hardware.h b/include/arch/i386/hardware.h index 0bfae9a4400..9550c5d214f 100644 --- a/include/arch/i386/hardware.h +++ b/include/arch/i386/hardware.h @@ -76,7 +76,11 @@ VOID DetectApmBios(FRLDRHKEY SystemKey, ULONG *BusNumber); VOID DetectCPUs(FRLDRHKEY SystemKey); /* hwpci.c */ -VOID DetectPciBios(FRLDRHKEY SystemKey, ULONG *BusNumber); +PCONFIGURATION_COMPONENT_DATA DetectPciBios(FRLDRHKEY SystemKey, + ULONG *BusNumber, + PCONFIGURATION_COMPONENT_DATA ComponentRoot, + PCONFIGURATION_COMPONENT_DATA PreviousComponent, + BOOLEAN NextChild); /* i386cpu.S */ ULONG CpuidSupported(VOID); diff --git a/include/arch/i386/machpc.h b/include/arch/i386/machpc.h index c87e756b936..155ec1c4af9 100644 --- a/include/arch/i386/machpc.h +++ b/include/arch/i386/machpc.h @@ -55,7 +55,7 @@ ULONG PcDiskGetCacheableBlockCount(ULONG DriveNumber); VOID PcRTCGetCurrentDateTime(PULONG Year, PULONG Month, PULONG Day, PULONG Hour, PULONG Minute, PULONG Second); -VOID PcHwDetect(VOID); +VOID PcHwDetect(PCONFIGURATION_COMPONENT_DATA *ComponentRoot); #endif /* __I386_MACHPC_H_ */ diff --git a/include/arch/i386/machxbox.h b/include/arch/i386/machxbox.h index 4f24dab4766..03f02844eb9 100644 --- a/include/arch/i386/machxbox.h +++ b/include/arch/i386/machxbox.h @@ -58,7 +58,7 @@ ULONG XboxDiskGetCacheableBlockCount(ULONG DriveNumber); VOID XboxRTCGetCurrentDateTime(PULONG Year, PULONG Month, PULONG Day, PULONG Hour, PULONG Minute, PULONG Second); -VOID XboxHwDetect(VOID); +VOID XboxHwDetect(PCONFIGURATION_COMPONENT_DATA *ComponentRoot); VOID XboxSetLED(PCSTR Pattern); diff --git a/include/machine.h b/include/machine.h index 51996a7a1e5..005518da754 100644 --- a/include/machine.h +++ b/include/machine.h @@ -69,7 +69,7 @@ typedef struct tagMACHVTBL VOID (*RTCGetCurrentDateTime)(PULONG Year, PULONG Month, PULONG Day, PULONG Hour, PULONG Minute, PULONG Second); - VOID (*HwDetect)(VOID); + VOID (*HwDetect)(PCONFIGURATION_COMPONENT_DATA *ComponentRoot); } MACHVTBL, *PMACHVTBL; VOID MachInit(const char *CmdLine); @@ -111,7 +111,7 @@ BOOLEAN MachDiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPAR BOOLEAN MachDiskGetDriveGeometry(ULONG DriveNumber, PGEOMETRY DriveGeometry); ULONG MachDiskGetCacheableBlockCount(ULONG DriveNumber); VOID MachRTCGetCurrentDateTime(PULONG Year, PULONG Month, PULONG Day, PULONG Hour, PULONG Minute, PULONG Second); -VOID MachHwDetect(VOID); +VOID MachHwDetect(PCONFIGURATION_COMPONENT_DATA *ComponentRoot); #define MachConsPutChar(Ch) MachVtbl.ConsPutChar(Ch) #define MachConsKbHit() MachVtbl.ConsKbHit() @@ -141,7 +141,7 @@ VOID MachHwDetect(VOID); #define MachDiskGetDriveGeometry(Drive, Geom) MachVtbl.DiskGetDriveGeometry((Drive), (Geom)) #define MachDiskGetCacheableBlockCount(Drive) MachVtbl.DiskGetCacheableBlockCount(Drive) #define MachRTCGetCurrentDateTime(Y, Mo, D, H, Mi, S) MachVtbl.RTCGetCurrentDateTime((Y), (Mo), (D), (H), (Mi), (S)); -#define MachHwDetect() MachVtbl.HwDetect() +#define MachHwDetect(ConfigRoot) MachVtbl.HwDetect((ConfigRoot)) #endif /* __MACHINE_H_ */ diff --git a/include/mm.h b/include/mm.h index 83c5fdf00c7..818fc9071b9 100644 --- a/include/mm.h +++ b/include/mm.h @@ -79,7 +79,7 @@ PVOID MmFindLocationForPageLookupTable(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG Map VOID MmSortBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount); // Sorts the BIOS_MEMORY_MAP array so the first element corresponds to the first address in memory VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount, PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount); // Inits the page lookup table according to the memory types in the memory map VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, TYPE_OF_MEMORY PageAllocated); // Marks the specified pages as allocated or free in the lookup table -VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount); // Allocates the specified pages in the lookup table +VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, TYPE_OF_MEMORY MemoryType); // Allocates the specified pages in the lookup table ULONG MmCountFreePagesInLookupTable(PVOID PageLookupTable, ULONG TotalPageCount); // Returns the number of free pages in the lookup table ULONG MmFindAvailablePages(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded, BOOLEAN FromEnd); // Returns the page number of the first available page range from the beginning or end of memory ULONG MmFindAvailablePagesBeforePage(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded, ULONG LastPage); // Returns the page number of the first available page range before the specified page @@ -94,11 +94,12 @@ PPAGE_LOOKUP_TABLE_ITEM MmGetMemoryMap(ULONG *NoEntries); // Returns a pointer //BOOLEAN MmInitializeMemoryManager(ULONG LowMemoryStart, ULONG LowMemoryLength); BOOLEAN MmInitializeMemoryManager(VOID); PVOID MmAllocateMemory(ULONG MemorySize); +PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType); VOID MmFreeMemory(PVOID MemoryPointer); VOID MmChangeAllocationPolicy(BOOLEAN PolicyAllocatePagesFromEnd); //PVOID MmAllocateLowMemory(ULONG MemorySize); //VOID MmFreeLowMemory(PVOID MemoryPointer); -PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress); -PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress); +PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY MemoryType); +PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY MemoryType); #endif // defined __MEMORY_H diff --git a/include/winldr.h b/include/winldr.h index 57ef9a6f59d..bd7b9f51379 100644 --- a/include/winldr.h +++ b/include/winldr.h @@ -40,8 +40,8 @@ NTAPI #define SECTOR_SIZE 512 // Descriptors -#define NUM_GDT 28 //15. The kernel wants 0xD8 as a last GDT entry offset -#define NUM_IDT 0x100 // only 16 are used though +#define NUM_GDT 128 // Must be 128 +#define NUM_IDT 0x100 // only 16 are used though. Must be 0x100 // conversion.c PVOID VaToPa(PVOID Va); @@ -52,6 +52,7 @@ VOID ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start); // peloader.c BOOLEAN WinLdrLoadImage(IN PCHAR FileName, + TYPE_OF_MEMORY MemoryType, OUT PVOID *ImageBasePA); diff --git a/linuxboot.c b/linuxboot.c index 27589bd6a26..2c5293766f9 100644 --- a/linuxboot.c +++ b/linuxboot.c @@ -375,7 +375,7 @@ BOOLEAN LinuxReadKernel(PFILE LinuxKernelFile) UiDrawStatusText(StatusText); // Allocate memory for Linux kernel - LinuxKernelLoadAddress = MmAllocateMemoryAtAddress(LinuxKernelSize, (PVOID)LINUX_KERNEL_LOAD_ADDRESS); + LinuxKernelLoadAddress = MmAllocateMemoryAtAddress(LinuxKernelSize, (PVOID)LINUX_KERNEL_LOAD_ADDRESS, LoaderSystemCode); if (LinuxKernelLoadAddress != (PVOID)LINUX_KERNEL_LOAD_ADDRESS) { return FALSE; @@ -452,11 +452,11 @@ BOOLEAN LinuxReadInitrd(PFILE LinuxInitrdFile) //LinuxInitrdLoadAddress = MmAllocateMemoryAtAddress(LinuxInitrdSize, (PVOID)ROUND_UP((LINUX_KERNEL_LOAD_ADDRESS + LinuxKernelSize), 0x100000)); if (LinuxSetupSector->Version <= 0x0202) { - LinuxInitrdLoadAddress = MmAllocateHighestMemoryBelowAddress(LinuxInitrdSize, (PVOID)LINUX_MAX_INITRD_ADDRESS); + LinuxInitrdLoadAddress = MmAllocateHighestMemoryBelowAddress(LinuxInitrdSize, (PVOID)LINUX_MAX_INITRD_ADDRESS, LoaderSystemCode); } else { - LinuxInitrdLoadAddress = MmAllocateHighestMemoryBelowAddress(LinuxInitrdSize, (PVOID)LinuxSetupSector->InitrdAddressMax); + LinuxInitrdLoadAddress = MmAllocateHighestMemoryBelowAddress(LinuxInitrdSize, (PVOID)LinuxSetupSector->InitrdAddressMax, LoaderSystemCode); } if (LinuxInitrdLoadAddress == NULL) { diff --git a/machine.c b/machine.c index 5d6933fa0ef..0d653aa95c9 100644 --- a/machine.c +++ b/machine.c @@ -228,9 +228,9 @@ MachRTCGetCurrentDateTime(PULONG Year, PULONG Month, PULONG Day, PULONG Hour, PU } VOID -MachHwDetect(VOID) +MachHwDetect(PCONFIGURATION_COMPONENT_DATA *ComponentRoot) { - MachVtbl.HwDetect(); + MachVtbl.HwDetect(ComponentRoot); } /* EOF */ diff --git a/mm/meminit.c b/mm/meminit.c index 9a5f20058c4..4e070676082 100644 --- a/mm/meminit.c +++ b/mm/meminit.c @@ -95,6 +95,27 @@ BOOLEAN MmInitializeMemoryManager(VOID) MmInitPageLookupTable(PageLookupTableAddress, TotalPagesInLookupTable, BiosMemoryMap, BiosMemoryMapEntryCount); MmUpdateLastFreePageHint(PageLookupTableAddress, TotalPagesInLookupTable); + // Add machine-dependent stuff + // FIXME: this is only for i386 +#if 0 + MmMarkPagesInLookupTable(PageLookupTableAddress, 0x00, 1, LoaderFirmwarePermanent); // realmode int vectors + MmMarkPagesInLookupTable(PageLookupTableAddress, 0x01, 7, LoaderFirmwareTemporary); // freeldr stack + cmdline + MmMarkPagesInLookupTable(PageLookupTableAddress, 0x08, 0x70, LoaderLoadedProgram); // freeldr image (roughly max. 0x64 pages) + MmMarkPagesInLookupTable(PageLookupTableAddress, 0x78, 8, LoaderOsloaderStack); // prot mode stack + + MmMarkPagesInLookupTable(PageLookupTableAddress, 0x80, 0x10, LoaderOsloaderHeap); // File system read buffer + MmMarkPagesInLookupTable(PageLookupTableAddress, 0x90, 0x10, LoaderOsloaderHeap); // Disk read buffer for int 13h + + MmMarkPagesInLookupTable(PageLookupTableAddress, 0xA0, 0x60, LoaderFirmwarePermanent); // ROM / Video +#endif + //HACK: Temporary, for test, remove soon + MmMarkPagesInLookupTable(PageLookupTableAddress, 0x00, 0x100, LoaderFirmwarePermanent); + + MmMarkPagesInLookupTable(PageLookupTableAddress, 0xFFF, 1, LoaderSpecialMemory); // unusable memory + + //HACK: Needed for ReactOS only! (KERNEL_BASE_PHYS >> MM_PAGE_SHIFT) + //MmMarkPagesInLookupTable(PageLookupTableAddress, 0x200, 0x300, LoaderFirmwareTemporary); // ReactOS kernel sits here + FreePagesInLookupTable = MmCountFreePagesInLookupTable(PageLookupTableAddress, TotalPagesInLookupTable); DbgPrint((DPRINT_MEMORY, "Memory Manager initialized. %d pages available.\n", FreePagesInLookupTable)); @@ -190,17 +211,50 @@ PVOID MmFindLocationForPageLookupTable(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG Map RtlCopyMemory(TempBiosMemoryMap, BiosMemoryMap, sizeof(BIOS_MEMORY_MAP) * 32); MmSortBiosMemoryMap(TempBiosMemoryMap, MapCount); - for (Index=(MapCount-1); Index>=0; Index--) + for (Index=0; Index= PageLookupTableSize) + + // place it somewhere @ 10Mb if possible + // (afaik no bad things are placed at 10Mb, if there are + // - we just fallback to the usual algo) + + // skip if this is not usable region + if (TempBiosMemoryMap[Index].Type != BiosMemoryUsable) + continue; + + if (TempBiosMemoryMap[Index].BaseAddress <= 10 * 0x100000 && + TempBiosMemoryMap[Index].BaseAddress + TempBiosMemoryMap[Index].Length >= + 10 * 0x100000 + PageLookupTableSize) { - PageLookupTableMemAddress = (PVOID)(ULONG)(TempBiosMemoryMap[Index].BaseAddress + (TempBiosMemoryMap[Index].Length - PageLookupTableSize)); + PageLookupTableMemAddress = (PVOID)(10 * 0x100000); break; } } + // Check if we found a suitable place + if (PageLookupTableMemAddress == 0) + { + // no, let's do a traditional algorithm instead + for (Index=(MapCount-1); Index>=0; Index--) + { + // If this is usable memory with a big enough length + // then we'll put our page lookup table here + + // skip if this is not usable region + if (TempBiosMemoryMap[Index].Type != BiosMemoryUsable) + continue; + + if (TempBiosMemoryMap[Index].Length >= PageLookupTableSize) + { + PageLookupTableMemAddress = (PVOID)(ULONG) + (TempBiosMemoryMap[Index].BaseAddress + (TempBiosMemoryMap[Index].Length - PageLookupTableSize)); + break; + } + } + } + DbgPrint((DPRINT_MEMORY, "MmFindLocationForPageLookupTable() returning 0x%x\n", PageLookupTableMemAddress)); return PageLookupTableMemAddress; @@ -243,7 +297,7 @@ VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount, PBIOS_ME // Mark every page as allocated initially // We will go through and mark pages again according to the memory map // But this will mark any holes not described in the map as allocated - MmMarkPagesInLookupTable(PageLookupTable, 0, TotalPageCount, 1); + MmMarkPagesInLookupTable(PageLookupTable, 0, TotalPageCount, LoaderFirmwarePermanent); for (Index=0; Index0; Index--) + for (Index=/*LastFreePageHint-1*/(16*1024*1024>>12)-1; Index>0; Index--) + //for (Index=LastFreePageHint-1; Index>0; Index--) { if (RealPageLookupTable[Index].PageAllocated != LoaderFree) { diff --git a/mm/mm.c b/mm/mm.c index 1e36519f4dc..9df8b979870 100644 --- a/mm/mm.c +++ b/mm/mm.c @@ -59,7 +59,7 @@ VOID MmChangeAllocationPolicy(BOOLEAN PolicyAllocatePagesFromEnd) AllocateFromEnd = PolicyAllocatePagesFromEnd; } -PVOID MmAllocateMemory(ULONG MemorySize) +PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType) { ULONG PagesNeeded; ULONG FirstFreePageFromEnd; @@ -102,7 +102,7 @@ PVOID MmAllocateMemory(ULONG MemorySize) return NULL; } - MmAllocatePagesInLookupTable(PageLookupTableAddress, FirstFreePageFromEnd, PagesNeeded); + MmAllocatePagesInLookupTable(PageLookupTableAddress, FirstFreePageFromEnd, PagesNeeded, MemoryType); FreePagesInLookupTable -= PagesNeeded; MemPointer = (PVOID)(FirstFreePageFromEnd * MM_PAGE_SIZE); @@ -125,7 +125,14 @@ PVOID MmAllocateMemory(ULONG MemorySize) return MemPointer; } -PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress) + +PVOID MmAllocateMemory(ULONG MemorySize) +{ + // Allocate it as "heap" + return MmAllocateMemoryWithType(MemorySize, LoaderOsloaderHeap); +} + +PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY MemoryType) { ULONG PagesNeeded; ULONG StartPageNumber; @@ -168,7 +175,7 @@ PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress) return NULL; } - MmAllocatePagesInLookupTable(PageLookupTableAddress, StartPageNumber, PagesNeeded); + MmAllocatePagesInLookupTable(PageLookupTableAddress, StartPageNumber, PagesNeeded, MemoryType); FreePagesInLookupTable -= PagesNeeded; MemPointer = (PVOID)(StartPageNumber * MM_PAGE_SIZE); @@ -184,7 +191,7 @@ PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress) return MemPointer; } -PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress) +PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY MemoryType) { ULONG PagesNeeded; ULONG FirstFreePageFromEnd; @@ -223,7 +230,7 @@ PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress return NULL; } - MmAllocatePagesInLookupTable(PageLookupTableAddress, FirstFreePageFromEnd, PagesNeeded); + MmAllocatePagesInLookupTable(PageLookupTableAddress, FirstFreePageFromEnd, PagesNeeded, MemoryType); FreePagesInLookupTable -= PagesNeeded; MemPointer = (PVOID)(FirstFreePageFromEnd * MM_PAGE_SIZE); @@ -377,7 +384,7 @@ VOID DumpMemoryAllocMap(VOID) if ((Idx % 32) == 0) { DbgPrint((DPRINT_MEMORY, "\n")); - DbgPrint((DPRINT_MEMORY, "%x:\t", (Idx * MM_PAGE_SIZE))); + DbgPrint((DPRINT_MEMORY, "%08x:\t", (Idx * MM_PAGE_SIZE))); } else if ((Idx % 4) == 0) { diff --git a/reactos/binhive.c b/reactos/binhive.c index 520e4f4d9be..72911baa935 100644 --- a/reactos/binhive.c +++ b/reactos/binhive.c @@ -680,6 +680,7 @@ RegImportSubKey(PHHIVE Hive, { HashCell = (PHASH_TABLE_CELL) HvGetCell (Hive, KeyCell->SubKeyLists[HvStable]); DbgPrint((DPRINT_REGISTRY, "HashCell: %x\n", HashCell)); + DbgPrint((DPRINT_REGISTRY, "HashCell->Id: %x\n", HashCell->Id)); DbgPrint((DPRINT_REGISTRY, "SubKeyCounts: %x\n", KeyCell->SubKeyCounts)); for (i = 0; i < KeyCell->SubKeyCounts[HvStable]; i++) diff --git a/reactos/reactos.c b/reactos/reactos.c index 5c60d63ca06..26777136c55 100644 --- a/reactos/reactos.c +++ b/reactos/reactos.c @@ -650,6 +650,7 @@ LoadAndBootReactOS(PCSTR OperatingSystemName) UINT i; CHAR MsgBuffer[256]; ULONG SectionId; + PCONFIGURATION_COMPONENT_DATA ConfigRoot; ULONG_PTR Base; ULONG Size; @@ -767,7 +768,7 @@ LoadAndBootReactOS(PCSTR OperatingSystemName) /* * Detect hardware */ - MachHwDetect(); + MachHwDetect(&ConfigRoot); UiDrawProgressBarCenter(5, 100, szLoadingMsg); if (AcpiPresent) LoaderBlock.Flags |= MB_FLAGS_ACPI_TABLE; diff --git a/reactos/setupldr.c b/reactos/setupldr.c index 87ebb1d4ee6..30618789ada 100644 --- a/reactos/setupldr.c +++ b/reactos/setupldr.c @@ -284,6 +284,7 @@ VOID RunLoader(VOID) const char *LoadOptions; UINT i; char szKernelName[256]; + PCONFIGURATION_COMPONENT_DATA ConfigRoot; HINF InfHandle; ULONG ErrorLine; @@ -354,7 +355,7 @@ VOID RunLoader(VOID) #else printf("Detecting hardware...\n\n"); #endif - MachHwDetect(); + MachHwDetect(&ConfigRoot); #ifdef USE_UI UiDrawStatusText(""); #endif diff --git a/windows/conversion.c b/windows/conversion.c index a42184bbfb4..ad1b621ae61 100644 --- a/windows/conversion.c +++ b/windows/conversion.c @@ -72,7 +72,7 @@ ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start) PCONFIGURATION_COMPONENT_DATA Child; PCONFIGURATION_COMPONENT_DATA Sibling; - DbgPrint((DPRINT_WINDOWS, "ConvertConfigToVA(Start 0x%X)", Start)); + DbgPrint((DPRINT_WINDOWS, "ConvertConfigToVA(Start 0x%X)\n", Start)); Child = Start; while (Child != NULL) @@ -89,11 +89,12 @@ ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start) if (Child->Sibling) Child->Sibling = PaToVa(Child->Sibling); - DbgPrint((DPRINT_WINDOWS, "Device 0x%X class %d", Child, Child->ComponentEntry.Class)); + DbgPrint((DPRINT_WINDOWS, "Device 0x%X class %d type %d, parent %p\n", Child, + Child->ComponentEntry.Class, Child->ComponentEntry.Type, Child->Parent)); // If the child has a sibling list, then search the sibling list // for an entry that matches the specified class, type, and key. - Sibling = Child->Sibling; + Sibling = VaToPa(Child->Sibling); while (Sibling != NULL) { if (Sibling->ConfigurationData) @@ -108,7 +109,8 @@ ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start) if (Sibling->Sibling) Sibling->Sibling = PaToVa(Sibling->Sibling); - DbgPrint((DPRINT_WINDOWS, "Device 0x%X class %d", Sibling, Sibling->ComponentEntry.Class)); + DbgPrint((DPRINT_WINDOWS, "Device 0x%X class %d type %d sib, parent %p\n", Sibling, + Sibling->ComponentEntry.Class, Sibling->ComponentEntry.Type, Sibling->Parent)); // If the sibling has a child tree, then search the child tree // for an entry that matches the specified class, type, and key. @@ -118,6 +120,7 @@ ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start) Sibling = VaToPa(Sibling->Sibling); } + // Go to the next child Child = VaToPa(Child->Child); } } diff --git a/windows/peloader.c b/windows/peloader.c index 2aeb30fbaca..9a02016abf3 100644 --- a/windows/peloader.c +++ b/windows/peloader.c @@ -1,5 +1,5 @@ /* - * PROJECT: WinLoader + * PROJECT: FreeLoader * LICENSE: GPL - See COPYING in the top level directory * FILE: freeldr/winldr/peloader.c * PURPOSE: Provides routines for loading PE files. To be merged with @@ -16,26 +16,146 @@ /* INCLUDES ***************************************************************/ #include -#define NDEBUG +//#define NDEBUG #include + +BOOLEAN +WinLdrpCompareDllName(IN PCH DllName, + IN PUNICODE_STRING UnicodeName); + +BOOLEAN +WinLdrpBindImportName(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, + IN PVOID DllBase, + IN PVOID ImageBase, + IN PIMAGE_THUNK_DATA ThunkData, + IN PIMAGE_EXPORT_DIRECTORY ExportDirectory, + IN ULONG ExportSize, + IN BOOLEAN ProcessForwards); + +BOOLEAN +WinLdrpLoadAndScanReferencedDll(PLOADER_PARAMETER_BLOCK WinLdrBlock, + PCCH DirectoryPath, + PCH ImportName, + PLDR_DATA_TABLE_ENTRY *DataTableEntry); + +BOOLEAN +WinLdrpScanImportAddressTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, + IN PVOID DllBase, + IN PVOID ImageBase, + IN PIMAGE_THUNK_DATA ThunkData); + + + /* FUNCTIONS **************************************************************/ +/* Returns TRUE if DLL has already been loaded - looks in LoadOrderList in LPB */ BOOLEAN WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, IN PCH DllName, OUT PLDR_DATA_TABLE_ENTRY *LoadedEntry) { + PLDR_DATA_TABLE_ENTRY DataTableEntry; + LIST_ENTRY *ModuleEntry; + + DbgPrint((DPRINT_WINDOWS, "WinLdrCheckForLoadedDll: DllName %X, LoadedEntry: %X\n", + DllName, LoadedEntry)); + + /* Just go through each entry in the LoadOrderList and compare loaded module's + name with a given name */ + ModuleEntry = WinLdrBlock->LoadOrderListHead.Flink; + while (ModuleEntry != &WinLdrBlock->LoadOrderListHead) + { + /* Get pointer to the current DTE */ + DataTableEntry = CONTAINING_RECORD(ModuleEntry, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); + + DbgPrint((DPRINT_WINDOWS, "WinLdrCheckForLoadedDll: DTE %p, EP %p\n", + DataTableEntry, DataTableEntry->EntryPoint)); + + /* Compare names */ + if (WinLdrpCompareDllName(DllName, &DataTableEntry->BaseDllName)) + { + /* Yes, found it, report pointer to the loaded module's DTE + to the caller and increase load count for it */ + *LoadedEntry = DataTableEntry; + DataTableEntry->LoadCount++; + DbgPrint((DPRINT_WINDOWS, "WinLdrCheckForLoadedDll: LoadedEntry %X\n", DataTableEntry)); + return TRUE; + } + + /* Go to the next entry */ + ModuleEntry = ModuleEntry->Flink; + } + + /* Nothing found */ return FALSE; } - BOOLEAN WinLdrScanImportDescriptorTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, IN PCCH DirectoryPath, IN PLDR_DATA_TABLE_ENTRY ScanDTE) { - return FALSE; + PLDR_DATA_TABLE_ENTRY DataTableEntry; + PIMAGE_IMPORT_DESCRIPTOR ImportTable; + ULONG ImportTableSize; + PCH ImportName; + BOOLEAN Status; + + /* Get a pointer to the import table of this image */ + ImportTable = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(VaToPa(ScanDTE->DllBase), + TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ImportTableSize); + + DbgPrint((DPRINT_WINDOWS, "WinLdrScanImportDescriptorTable(): %S ImportTable = 0x%X\n", + VaToPa(ScanDTE->BaseDllName.Buffer),ImportTable)); + + /* If image doesn't have any import directory - just return success */ + if (ImportTable == NULL) + return TRUE; + + /* Loop through all entries */ + for (;(ImportTable->Name != 0) && (ImportTable->FirstThunk != NULL);ImportTable++) + { + /* Get pointer to the name */ + ImportName = (PCH)VaToPa(RVA(ScanDTE->DllBase, ImportTable->Name)); + DbgPrint((DPRINT_WINDOWS, "WinLdrScanImportDescriptorTable(): Looking at %s\n", ImportName)); + + /* In case we get a reference to ourselves - just skip it */ + if (WinLdrpCompareDllName(ImportName, &ScanDTE->BaseDllName)) + continue; + + /* Load the DLL if it is not already loaded */ + if (!WinLdrCheckForLoadedDll(WinLdrBlock, ImportName, &DataTableEntry)) + { + Status = WinLdrpLoadAndScanReferencedDll(WinLdrBlock, + DirectoryPath, + ImportName, + &DataTableEntry); + + if (!Status) + { + DbgPrint((DPRINT_WINDOWS, "WinLdrpLoadAndScanReferencedDll() failed\n")); + return Status; + } + } + + /* Scan its import address table */ + Status = WinLdrpScanImportAddressTable( + WinLdrBlock, + DataTableEntry->DllBase, + ScanDTE->DllBase, + (PIMAGE_THUNK_DATA)RVA(ScanDTE->DllBase, ImportTable->FirstThunk)); + + if (!Status) + { + DbgPrint((DPRINT_WINDOWS, "WinLdrpScanImportAddressTable() failed\n")); + return Status; + } + } + + return TRUE; } BOOLEAN @@ -63,8 +183,7 @@ WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, /* Initialize corresponding fields of DTE based on NT headers value */ DataTableEntry->DllBase = BaseVA; DataTableEntry->SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage; - DataTableEntry->EntryPoint = (PVOID)((ULONG)BaseVA + - NtHeaders->OptionalHeader.AddressOfEntryPoint); + DataTableEntry->EntryPoint = RVA(BaseVA, NtHeaders->OptionalHeader.AddressOfEntryPoint); DataTableEntry->SectionPointer = 0; DataTableEntry->CheckSum = NtHeaders->OptionalHeader.CheckSum; @@ -123,6 +242,7 @@ WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, */ BOOLEAN WinLdrLoadImage(IN PCHAR FileName, + TYPE_OF_MEMORY MemoryType, OUT PVOID *ImageBasePA) { PFILE FileHandle; @@ -135,7 +255,11 @@ WinLdrLoadImage(IN PCHAR FileName, BOOLEAN Status; ULONG i, BytesRead; - //Print(L"Loading %s... ", FileName); + CHAR ProgressString[256]; + + /* Inform user we are loading files */ + sprintf(ProgressString, "Loading %s...", FileName); + UiDrawProgressBarCenter(1, 100, ProgressString); /* Open the image file */ FileHandle = FsOpenFile(FileName); @@ -183,14 +307,15 @@ WinLdrLoadImage(IN PCHAR FileName, /* Try to allocate this memory, if fails - allocate somewhere else */ PhysicalBase = MmAllocateMemoryAtAddress(NtHeaders->OptionalHeader.SizeOfImage, - (PVOID)NtHeaders->OptionalHeader.ImageBase); + (PVOID)((ULONG)NtHeaders->OptionalHeader.ImageBase & (KSEG0_BASE - 1)), + MemoryType); if (PhysicalBase == NULL) { /* It's ok, we don't panic - let's allocate again at any other "low" place */ - MmChangeAllocationPolicy(FALSE); - PhysicalBase = MmAllocateMemory(NtHeaders->OptionalHeader.SizeOfImage); - MmChangeAllocationPolicy(TRUE); + //MmChangeAllocationPolicy(FALSE); + PhysicalBase = MmAllocateMemoryWithType(NtHeaders->OptionalHeader.SizeOfImage, MemoryType); + //MmChangeAllocationPolicy(TRUE); if (PhysicalBase == NULL) { @@ -263,12 +388,18 @@ WinLdrLoadImage(IN PCHAR FileName, Status = FsReadFile(FileHandle, SizeOfRawData, &BytesRead, (PUCHAR)PhysicalBase + SectionHeader->VirtualAddress); if (!Status && (BytesRead == 0)) + { + DbgPrint((DPRINT_WINDOWS, "WinLdrLoadImage(): Error reading section from file!\n")); break; + } } /* Size of data is less than the virtual size - fill up the remainder with zeroes */ if (SizeOfRawData < VirtualSize) + { + DbgPrint((DPRINT_WINDOWS, "WinLdrLoadImage(): SORD %d < VS %d", SizeOfRawData, VirtualSize)); RtlZeroMemory((PVOID)(SectionHeader->VirtualAddress + (ULONG)PhysicalBase + SizeOfRawData), VirtualSize - SizeOfRawData); + } SectionHeader++; } @@ -298,3 +429,394 @@ WinLdrLoadImage(IN PCHAR FileName, } /* PRIVATE FUNCTIONS *******************************************************/ + +/* DllName - physical, UnicodeString->Buffer - virtual */ +BOOLEAN +WinLdrpCompareDllName(IN PCH DllName, + IN PUNICODE_STRING UnicodeName) +{ + PWSTR Buffer; + UNICODE_STRING UnicodeNamePA; + ULONG i, Length; + + /* First obvious check: for length of two names */ + Length = strlen(DllName); + + UnicodeNamePA.Length = UnicodeName->Length; + UnicodeNamePA.MaximumLength = UnicodeName->MaximumLength; + UnicodeNamePA.Buffer = VaToPa(UnicodeName->Buffer); + DbgPrint((DPRINT_WINDOWS, "WinLdrpCompareDllName: %s and %wZ, Length = %d " + "UN->Length %d\n", DllName, &UnicodeNamePA, Length, UnicodeName->Length)); + + if ((Length * sizeof(WCHAR)) > UnicodeName->Length) + return FALSE; + + /* Store pointer to unicode string's buffer */ + Buffer = VaToPa(UnicodeName->Buffer); + + /* Loop character by character */ + for (i = 0; i < Length; i++) + { + /* Compare two characters, uppercasing them */ + if (toupper(*DllName) != toupper((CHAR)*Buffer)) + return FALSE; + + /* Move to the next character */ + DllName++; + Buffer++; + } + + /* Check, if strings either fully match, or match till the "." (w/o extension) */ + if ((UnicodeName->Length == Length * sizeof(WCHAR)) || (*Buffer == L'.')) + { + /* Yes they do */ + return TRUE; + } + + /* Strings don't match, return FALSE */ + return FALSE; +} + +BOOLEAN +WinLdrpBindImportName(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, + IN PVOID DllBase, + IN PVOID ImageBase, + IN PIMAGE_THUNK_DATA ThunkData, + IN PIMAGE_EXPORT_DIRECTORY ExportDirectory, + IN ULONG ExportSize, + IN BOOLEAN ProcessForwards) +{ + ULONG Ordinal; + PULONG NameTable, FunctionTable; + PUSHORT OrdinalTable; + LONG High, Low, Middle, Result; + ULONG Hint; + + //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): DllBase 0x%X, ImageBase 0x%X, ThunkData 0x%X, ExportDirectory 0x%X, ExportSize %d, ProcessForwards 0x%X\n", + // DllBase, ImageBase, ThunkData, ExportDirectory, ExportSize, ProcessForwards)); + + /* Check passed DllBase param */ + if(DllBase == NULL) + { + DbgPrint((DPRINT_WINDOWS, "WARNING: DllBase == NULL!\n")); + return FALSE; + } + + /* Convert all non-critical pointers to PA from VA */ + ThunkData = VaToPa(ThunkData); + + /* Is the reference by ordinal? */ + if (IMAGE_SNAP_BY_ORDINAL(ThunkData->u1.Ordinal) && !ProcessForwards) + { + /* Yes, calculate the ordinal */ + Ordinal = (ULONG)(IMAGE_ORDINAL(ThunkData->u1.Ordinal) - (UINT32)ExportDirectory->Base); + //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): Ordinal %d\n", Ordinal)); + } + else + { + /* It's reference by name, we have to look it up in the export directory */ + if (!ProcessForwards) + { + /* AddressOfData in thunk entry will become a virtual address (from relative) */ + //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): ThunkData->u1.AOD was %p\n", ThunkData->u1.AddressOfData)); + ThunkData->u1.AddressOfData = + (PIMAGE_IMPORT_BY_NAME)RVA(ImageBase, ThunkData->u1.AddressOfData); + //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): ThunkData->u1.AOD became %p\n", ThunkData->u1.AddressOfData)); + } + + /* Get pointers to Name and Ordinal tables (RVA -> VA) */ + NameTable = (PULONG)VaToPa(RVA(DllBase, ExportDirectory->AddressOfNames)); + OrdinalTable = (PUSHORT)VaToPa(RVA(DllBase, ExportDirectory->AddressOfNameOrdinals)); + + //DbgPrint((DPRINT_WINDOWS, "NameTable 0x%X, OrdinalTable 0x%X, ED->AddressOfNames 0x%X, ED->AOFO 0x%X\n", + // NameTable, OrdinalTable, ExportDirectory->AddressOfNames, ExportDirectory->AddressOfNameOrdinals)); + + /* Get the hint, convert it to a physical pointer */ + Hint = ((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Hint; + //DbgPrint((DPRINT_WINDOWS, "HintIndex %d\n", Hint)); + + /* If Hint is less than total number of entries in the export directory, + and import name == export name, then we can just get it from the OrdinalTable */ + if ( + (Hint < ExportDirectory->NumberOfNames) && + ( + strcmp(VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name[0]), + (PCHAR)VaToPa( RVA(DllBase, NameTable[Hint])) ) == 0 + ) + ) + { + Ordinal = OrdinalTable[Hint]; + //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): Ordinal %d\n", Ordinal)); + } + else + { + /* It's not the easy way, we have to lookup import name in the name table. + Let's use a binary search for this task. */ + + //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName() looking up the import name using binary search...\n")); + + /* Low boundary is set to 0, and high boundary to the maximum index */ + Low = 0; + High = ExportDirectory->NumberOfNames - 1; + + /* Perform a binary-search loop */ + while (High >= Low) + { + /* Divide by 2 by shifting to the right once */ + Middle = (Low + High) >> 1; + + /* Compare the names */ + Result = strcmp(VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name[0]), + (PCHAR)VaToPa(RVA(DllBase, NameTable[Middle]))); + + DbgPrint((DPRINT_WINDOWS, "Binary search: comparing Import '__', Export '%s'\n", + /*VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name[0]),*/ + (PCHAR)VaToPa(RVA(DllBase, NameTable[Middle])))); + + DbgPrint((DPRINT_WINDOWS, "TE->u1.AOD %p, fulladdr %p\n", + ThunkData->u1.AddressOfData, + ((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name )); + + + /* Depending on result of strcmp, perform different actions */ + if (Result < 0) + { + /* Adjust top boundary */ + High = Middle - 1; + } + else if (Result > 0) + { + /* Adjust bottom boundary */ + Low = Middle + 1; + } + else + { + /* Yay, found it! */ + break; + } + } + + /* If high boundary is less than low boundary, then no result found */ + if (High < Low) + { + //Print(L"Error in binary search\n"); + DbgPrint((DPRINT_WINDOWS, "Error in binary search!\n")); + return FALSE; + } + + /* Everything allright, get the ordinal */ + Ordinal = OrdinalTable[Middle]; + + //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName() found Ordinal %d\n", Ordinal)); + } + } + + /* Check ordinal number for validity! */ + if (Ordinal >= ExportDirectory->NumberOfFunctions) + { + DbgPrint((DPRINT_WINDOWS, "Ordinal number is invalid!\n")); + return FALSE; + } + + /* Get a pointer to the function table */ + FunctionTable = (PULONG)VaToPa(RVA(DllBase, ExportDirectory->AddressOfFunctions)); + + /* Save a pointer to the function */ + ThunkData->u1.Function = (PULONG)RVA(DllBase, FunctionTable[Ordinal]); + + /* Is it a forwarder? (function pointer isn't within the export directory) */ + if (((ULONG)VaToPa(ThunkData->u1.Function) > (ULONG)ExportDirectory) && + ((ULONG)VaToPa(ThunkData->u1.Function) < ((ULONG)ExportDirectory + ExportSize))) + { + PLDR_DATA_TABLE_ENTRY DataTableEntry; + CHAR ForwardDllName[255]; + PIMAGE_EXPORT_DIRECTORY RefExportDirectory; + ULONG RefExportSize; + + /* Save the name of the forward dll */ + RtlCopyMemory(ForwardDllName, (PCHAR)VaToPa(ThunkData->u1.Function), sizeof(ForwardDllName)); + + /* Strip out its extension */ + *strchr(ForwardDllName,'.') = '\0'; + + DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): ForwardDllName %s\n", ForwardDllName)); + if (!WinLdrCheckForLoadedDll(WinLdrBlock, ForwardDllName, &DataTableEntry)) + { + /* We can't continue if DLL couldn't be loaded, so bomb out with an error */ + //Print(L"Error loading DLL!\n"); + DbgPrint((DPRINT_WINDOWS, "Error loading DLL!\n")); + return FALSE; + } + + /* Get pointer to the export directory of loaded DLL */ + RefExportDirectory = (PIMAGE_EXPORT_DIRECTORY) + RtlImageDirectoryEntryToData(VaToPa(DataTableEntry->DllBase), + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &RefExportSize); + + /* Fail if it's NULL */ + if (RefExportDirectory) + { + UCHAR Buffer[128]; + IMAGE_THUNK_DATA RefThunkData; + PIMAGE_IMPORT_BY_NAME ImportByName; + PCHAR ImportName; + BOOLEAN Status; + + /* Get pointer to the import name */ + ImportName = strchr((PCHAR)VaToPa(ThunkData->u1.Function), '.') + 1; + + /* Create a IMAGE_IMPORT_BY_NAME structure, pointing to the local Buffer */ + ImportByName = (PIMAGE_IMPORT_BY_NAME)Buffer; + + /* Fill the name with the import name */ + RtlCopyMemory(ImportByName->Name, ImportName, strlen(ImportName)+1); + + /* Set Hint to 0 */ + ImportByName->Hint = 0; + + /* And finally point ThunkData's AddressOfData to that structure */ + RefThunkData.u1.AddressOfData = ImportByName; + + /* And recursively call ourselves */ + Status = WinLdrpBindImportName( + WinLdrBlock, + DataTableEntry->DllBase, + ImageBase, + &RefThunkData, + RefExportDirectory, + RefExportSize, + TRUE); + + /* Fill out the ThunkData with data from RefThunkData */ + ThunkData->u1 = RefThunkData.u1; + + /* Return what we got from the recursive call */ + return Status; + } + else + { + /* Fail if ExportDirectory is NULL */ + return FALSE; + } + } + + /* Success! */ + return TRUE; +} + +BOOLEAN +WinLdrpLoadAndScanReferencedDll(PLOADER_PARAMETER_BLOCK WinLdrBlock, + PCCH DirectoryPath, + PCH ImportName, + PLDR_DATA_TABLE_ENTRY *DataTableEntry) +{ + CHAR FullDllName[256]; + BOOLEAN Status; + PVOID BasePA; + + /* Prepare the full path to the file to be loaded */ + strcpy(FullDllName, DirectoryPath); + strcat(FullDllName, ImportName); + + DbgPrint((DPRINT_WINDOWS, "Loading referenced DLL: %s\n", FullDllName)); + //Print(L"Loading referenced DLL: %s\n", FullDllName); + + /* Load the image */ + Status = WinLdrLoadImage(FullDllName, LoaderHalCode, &BasePA); + + if (!Status) + { + DbgPrint((DPRINT_WINDOWS, "WinLdrLoadImage() failed\n")); + return Status; + } + + /* Allocate DTE for newly loaded DLL */ + Status = WinLdrAllocateDataTableEntry(WinLdrBlock, + ImportName, + FullDllName, + BasePA, + DataTableEntry); + + if (!Status) + { + DbgPrint((DPRINT_WINDOWS, + "WinLdrAllocateDataTableEntry() failed with Status=0x%X\n", Status)); + return Status; + } + + /* Scan its dependencies too */ + DbgPrint((DPRINT_WINDOWS, + "WinLdrScanImportDescriptorTable() calling ourselves for %S\n", + VaToPa((*DataTableEntry)->BaseDllName.Buffer))); + Status = WinLdrScanImportDescriptorTable(WinLdrBlock, DirectoryPath, *DataTableEntry); + + if (!Status) + { + DbgPrint((DPRINT_WINDOWS, + "WinLdrScanImportDescriptorTable() failed with Status=0x%X\n", Status)); + return Status; + } + + return TRUE; +} + +BOOLEAN +WinLdrpScanImportAddressTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, + IN PVOID DllBase, + IN PVOID ImageBase, + IN PIMAGE_THUNK_DATA ThunkData) +{ + PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; + BOOLEAN Status; + ULONG ExportSize; + + DbgPrint((DPRINT_WINDOWS, "WinLdrpScanImportAddressTable(): DllBase 0x%X, " + "ImageBase 0x%X, ThunkData 0x%X\n", DllBase, ImageBase, ThunkData)); + + /* Obtain the export table from the DLL's base */ + if (DllBase == NULL) + { + //Print(L"Error, DllBase == NULL!\n"); + return FALSE; + } + else + { + ExportDirectory = + (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(VaToPa(DllBase), + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportSize); + } + + DbgPrint((DPRINT_WINDOWS, "WinLdrpScanImportAddressTable(): ExportDirectory 0x%X\n", ExportDirectory)); + + /* If pointer to Export Directory is */ + if (ExportDirectory == NULL) + return FALSE; + + /* Go through each entry in the thunk table and bind it */ + while (((PIMAGE_THUNK_DATA)VaToPa(ThunkData))->u1.AddressOfData != NULL) + { + /* Bind it */ + Status = WinLdrpBindImportName( + WinLdrBlock, + DllBase, + ImageBase, + ThunkData, + ExportDirectory, + ExportSize, + FALSE); + + /* Move to the next entry */ + ThunkData++; + + /* Return error if binding was unsuccessful */ + if (!Status) + return Status; + } + + /* Return success */ + return TRUE; +} diff --git a/windows/winldr.c b/windows/winldr.c index 33e51b105bc..b5bbf1acb2f 100644 --- a/windows/winldr.c +++ b/windows/winldr.c @@ -45,34 +45,49 @@ VOID WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock); VOID WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock); VOID WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock); - -void InitializeHWConfig(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock) +//TODO: Move to arch-independent hardware.c file +PVOID +HwCreateComponentResources(PCONFIGURATION_COMPONENT Component, + ULONG DeviceDataLength, + PVOID DeviceData) { - PCONFIGURATION_COMPONENT_DATA ConfigurationRoot; - PCONFIGURATION_COMPONENT Component; - PCONFIGURATION_COMPONENT_DATA /*CurrentEntry,*/ PreviousEntry, AdapterEntry; - BOOLEAN IsNextEntryChild; + return NULL; +} + +//TODO: Move to arch-independent hardware.c file +VOID +InitializeHWConfig(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + //PCONFIGURATION_COMPONENT_DATA ConfigurationRoot; + //PCONFIGURATION_COMPONENT Component; + //PCONFIGURATION_COMPONENT_DATA /*CurrentEntry,*/ PreviousEntry, AdapterEntry; + //BOOLEAN IsNextEntryChild; DbgPrint((DPRINT_WINDOWS, "InitializeHWConfig()\n")); - LoaderBlock->ConfigurationRoot = MmAllocateMemory(sizeof(CONFIGURATION_COMPONENT_DATA)); - RtlZeroMemory(LoaderBlock->ConfigurationRoot, sizeof(CONFIGURATION_COMPONENT_DATA)); + //LoaderBlock->ConfigurationRoot = MmAllocateMemory(sizeof(CONFIGURATION_COMPONENT_DATA)); + //RtlZeroMemory(LoaderBlock->ConfigurationRoot, sizeof(CONFIGURATION_COMPONENT_DATA)); /* Fill root == SystemClass */ - ConfigurationRoot = LoaderBlock->ConfigurationRoot; - Component = &LoaderBlock->ConfigurationRoot->ComponentEntry; + //ConfigurationRoot = LoaderBlock->ConfigurationRoot; + //Component = &LoaderBlock->ConfigurationRoot->ComponentEntry; - Component->Class = SystemClass; - Component->Type = MaximumType; - Component->Version = 0; // FIXME: ? - Component->Key = 0; - Component->AffinityMask = 0; + //Component->Class = SystemClass; + //Component->Type = MaximumType; + //Component->Version = 0; // FIXME: ? + //Component->ConfigurationDataLength = 0; + //Component->Key = 0; + //Component->AffinityMask = 0; - IsNextEntryChild = TRUE; - PreviousEntry = ConfigurationRoot; + //Component->Identifier = 0; + //Component->IdentifierLength = 0; + + + //IsNextEntryChild = TRUE; + //PreviousEntry = ConfigurationRoot; /* Enumerate all PCI buses */ - AdapterEntry = ConfigurationRoot; + //AdapterEntry = ConfigurationRoot; /* TODO: Disk Geometry */ /* TODO: Keyboard */ @@ -118,12 +133,12 @@ AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock) VOID WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock) { - //CHAR Options[] = "/CRASHDEBUG /DEBUGPORT=COM1 /BAUDRATE=115200"; - CHAR Options[] = "/NODEBUG"; + CHAR Options[] = "/DEBUGPORT=COM1 /BAUDRATE=115200"; + //CHAR Options[] = "/NODEBUG"; CHAR SystemRoot[] = "\\WINNT\\"; CHAR HalPath[] = "\\"; - CHAR ArcBoot[] = "multi(0)disk(0)rdisk(1)partition(1)"; - CHAR ArcHal[] = "multi(0)disk(0)rdisk(1)partition(1)"; + CHAR ArcBoot[] = "multi(0)disk(0)rdisk(0)partition(1)"; + CHAR ArcHal[] = "multi(0)disk(0)rdisk(0)partition(1)"; ULONG i; PLOADER_PARAMETER_EXTENSION Extension; @@ -165,15 +180,20 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock) PARC_DISK_SIGNATURE ArcDiskInfo; /* Get the ARC structure */ - ArcDiskInfo = &BldrDiskInfo[i]; + ArcDiskInfo = (PARC_DISK_SIGNATURE)MmAllocateMemory(sizeof(ARC_DISK_SIGNATURE));//&BldrDiskInfo[i]; + RtlZeroMemory(ArcDiskInfo, sizeof(ARC_DISK_SIGNATURE)); /* Copy the data over */ ArcDiskInfo->Signature = reactos_arc_disk_info[i].Signature; ArcDiskInfo->CheckSum = reactos_arc_disk_info[i].CheckSum; /* Copy the ARC Name */ + //ArcDiskInfo->ArcName = (PCHAR)MmAllocateMemory(sizeof(CHAR)*256); strcpy(BldrArcNames[i], reactos_arc_disk_info[i].ArcName); - ArcDiskInfo->ArcName = BldrArcNames[i]; + ArcDiskInfo->ArcName = (PCHAR)PaToVa(BldrArcNames[i]); + + /* Mark partition table as valid */ + ArcDiskInfo->ValidPartitionTable = TRUE; /* Insert into the list */ InsertTailList(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead, @@ -187,16 +207,17 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock) /* Create configuration entries */ InitializeHWConfig(LoaderBlock); - /* Convert all DTE into virtual addresses */ - //TODO: !!! - + /* Convert all list's to Virtual address */ + + /* Convert all DTE into virtual addresses */ List_PaToVa(&LoaderBlock->LoadOrderListHead); /* this one will be converted right before switching to virtual paging mode */ //List_PaToVa(&LoaderBlock->MemoryDescriptorListHead); + /* Convert list of boot drivers */ List_PaToVa(&LoaderBlock->BootDriverListHead); /* Initialize Extension now */ @@ -232,7 +253,7 @@ void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock, //LoaderBlock->u.I386.MachineType = MachineType; //FIXME: MachineType? /* Allocate 2 pages for PCR */ - Pcr = (ULONG_PTR)MmAllocateMemory(2 * MM_PAGE_SIZE); + Pcr = (ULONG_PTR)MmAllocateMemoryWithType(2 * MM_PAGE_SIZE, LoaderStartupPcrPage); *PcrBasePage = Pcr >> MM_PAGE_SHIFT; if (Pcr == 0) @@ -245,7 +266,7 @@ void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock, TssSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1); TssPages = TssSize / MM_PAGE_SIZE; - Tss = (ULONG_PTR)MmAllocateMemory(TssSize); + Tss = (ULONG_PTR)MmAllocateMemoryWithType(TssSize, LoaderMemoryData); *TssBasePage = Tss >> MM_PAGE_SHIFT; @@ -303,7 +324,7 @@ WinLdrLoadDeviceDriver(PLOADER_PARAMETER_BLOCK LoaderBlock, // It's not loaded, we have to load it sprintf(FullPath,"%s%wZ", BootPath, FilePath); - Status = WinLdrLoadImage(FullPath, &DriverBase); + Status = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase); if (!Status) return FALSE; @@ -346,8 +367,8 @@ WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, { BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, ListEntry); - //DbgPrint((DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath, - // BootDriver->DataTableEntry, &BootDriver->RegistryPath)); + DbgPrint((DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath, + BootDriver->DataTableEntry, &BootDriver->RegistryPath)); // Paths are relative (FIXME: Are they always relative?) @@ -363,6 +384,10 @@ WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, return FALSE; } + // Convert the RegistryPath and DTE addresses to VA since we are not going to use it anymore + BootDriver->RegistryPath.Buffer = PaToVa(BootDriver->RegistryPath.Buffer); + BootDriver->DataTableEntry = PaToVa(BootDriver->DataTableEntry); + NextBd = BootDriver->ListEntry.Flink; } @@ -421,9 +446,6 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion) return; } - /* Detect hardware */ - MachHwDetect(); - UiDrawStatusText("Loading..."); /* Try to open system drive */ @@ -444,16 +466,19 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion) // Allocate and minimalistic-initialize LPB AllocateAndInitLPB(&LoaderBlock); + // Detect hardware + MachHwDetect(&LoaderBlock->ConfigurationRoot); + // Load kernel strcpy(FileName, BootPath); strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE"); - Status = WinLdrLoadImage(FileName, &NtosBase); + Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase); DbgPrint((DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase)); // Load HAL strcpy(FileName, BootPath); strcat(FileName, "SYSTEM32\\HAL.DLL"); - Status = WinLdrLoadImage(FileName, &HalBase); + Status = WinLdrLoadImage(FileName, LoaderHalCode, &HalBase); DbgPrint((DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase)); // Load kernel-debugger support dll @@ -461,7 +486,7 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion) { strcpy(FileName, BootPath); strcat(FileName, "SYSTEM32\\KDCOM.DLL"); - Status = WinLdrLoadImage(FileName, &KdComBase); + Status = WinLdrLoadImage(FileName, LoaderBootDriver, &KdComBase); DbgPrint((DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase)); } @@ -503,6 +528,10 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion) LoaderBlockVA = PaToVa(LoaderBlock); + /* "Stop all motors", change videomode */ + DiskStopFloppyMotor(); + MachVideoPrepareForReactOS(); + /* Debugging... */ //DumpMemoryAllocMap(); @@ -523,7 +552,7 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion) asm("jmp test1\n"); asm(".att_syntax\n");*/ - + /* Pass control */ (*KiSystemStartup)(LoaderBlockVA); return; diff --git a/windows/wlmemory.c b/windows/wlmemory.c index 82511c71ae9..1ecaf0d43cf 100644 --- a/windows/wlmemory.c +++ b/windows/wlmemory.c @@ -28,33 +28,31 @@ extern ULONG TotalNLSSize; #define HYPER_SPACE_ENTRY 0x300 -//TODO: Check if this is correct PCHAR MemTypeDesc[] = { - "ExceptionBlock ", - "SystemBlock ", + "ExceptionBlock ", // ? + "SystemBlock ", // ? "Free ", - "Bad ", - "LoadedProgram ", - "FirmwareTemporary ", - "FirmwarePermanent ", - "OsloaderHeap ", - "OsloaderStack ", + "Bad ", // used + "LoadedProgram ", // == Free + "FirmwareTemporary ", // == Free + "FirmwarePermanent ", // == Bad + "OsloaderHeap ", // used + "OsloaderStack ", // == Free "SystemCode ", "HalCode ", - "BootDriver ", - "ConsoleInDriver ", - "ConsoleOutDriver ", - "StartupDpcStack ", - "StartupKernelStack", - "StartupPanicStack ", - "StartupPcrPage ", - "StartupPdrPage ", - "RegistryData ", - "MemoryData ", - "NlsData ", - "SpecialMemory ", - "BBTMemory ", - "Maximum " + "BootDriver ", // not used + "ConsoleInDriver ", // ? + "ConsoleOutDriver ", // ? + "StartupDpcStack ", // ? + "StartupKernelStack", // ? + "StartupPanicStack ", // ? + "StartupPcrPage ", // ? + "StartupPdrPage ", // ? + "RegistryData ", // used + "MemoryData ", // not used + "NlsData ", // used + "SpecialMemory ", // == Bad + "BBTMemory " // == Bad }; VOID @@ -63,8 +61,8 @@ WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock); VOID MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, - UINT64 BasePage, - UINT64 PageCount, + ULONG BasePage, + ULONG PageCount, ULONG Type); VOID WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, @@ -138,8 +136,9 @@ MempAllocatePageTables() // Allocate memory block for all these things: // PDE, HAL mapping page table, physical mapping, kernel mapping + // FIXME: PDE+HAL+KernelPTEs == FirmwarePermanent, Physical PTEs = FirmwareTemporary TotalSize = (1+1+NumPageTables*2)*MM_PAGE_SIZE; - Buffer = MmAllocateMemory(TotalSize); + Buffer = MmAllocateMemoryWithType(TotalSize, LoaderFirmwarePermanent); if (Buffer == NULL) { @@ -269,8 +268,8 @@ MempSetupPaging(IN ULONG StartPage, VOID MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, - UINT64 BasePage, - UINT64 PageCount, + ULONG BasePage, + ULONG PageCount, ULONG Type) { BOOLEAN Status; @@ -296,72 +295,32 @@ MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, // Check if it's more than the allowed for OS loader // if yes - don't map the pages, just add as FirmwareTemporary // - if (BasePage + PageCount > LOADER_HIGH_ZONE && (Type != LoaderNlsData)) + if (BasePage + PageCount > LOADER_HIGH_ZONE) { Mad[MadCount].MemoryType = LoaderFirmwareTemporary; WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); MadCount++; - Status = MempSetupPaging(BasePage, PageCount); - if (!Status) - { - DbgPrint((DPRINT_WINDOWS, "Error during WinLdrpSetupPaging\n")); - return; - } return; } - if (BasePage == 0xFFF && PageCount == 1) + // + // Set memory type + // + Mad[MadCount].MemoryType = Type; + + // + // Add descriptor + // + WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); + MadCount++; + + // + // Map it + // + if (BasePage >= 0x100) { - Mad[MadCount].MemoryType = LoaderSpecialMemory; - - WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); - MadCount++; - - // - // Map it - // - Status = MempSetupPaging(BasePage, PageCount); - if (!Status) - { - DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging\n")); - return; - } - } - else if (BasePage == 0 && PageCount == 1) - { - Mad[MadCount].MemoryType = LoaderFirmwarePermanent; - - WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); - MadCount++; - - // - // Map it - // - Status = MempSetupPaging(BasePage, PageCount); - if (!Status) - { - DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging\n")); - return; - } - } - else - { - // - // Set memory type - // - Mad[MadCount].MemoryType = Type; - - // - // Add descriptor - // - WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); - MadCount++; - - // - // Map it - // Status = MempSetupPaging(BasePage, PageCount); if (!Status) { @@ -378,12 +337,11 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, PVOID GdtIdt) { ULONG i, PagesCount; - ULONG LastPageIndex, LastPageType, NtType; + ULONG LastPageIndex, LastPageType; PPAGE_LOOKUP_TABLE_ITEM MemoryMap; ULONG NoEntries; PKTSS Tss; - PVOID NlsBase = VaToPa(((PNLS_DATA_BLOCK)VaToPa(LoaderBlock->NlsData))->AnsiCodePageData); - ULONG NlsBasePage = (ULONG_PTR)NlsBase >> PAGE_SHIFT; + BOOLEAN Status; // // Creating a suitable memory map for the Windows can be tricky, so let's @@ -420,8 +378,15 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, return FALSE; } - DbgPrint((DPRINT_WINDOWS, "Got memory map with %d entries, NlsBasePage 0x%X\n", - NoEntries, NlsBasePage)); + DbgPrint((DPRINT_WINDOWS, "Got memory map with %d entries\n", NoEntries)); + + // Always contigiously map low 1Mb of memory + Status = MempSetupPaging(0, 0x100); + if (!Status) + { + DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging of low 1Mb\n")); + return FALSE; + } // Construct a good memory map from what we've got PagesCount = 1; @@ -430,66 +395,14 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, for(i=1;i NlsBasePage+TotalNLSSize) && (i != NoEntries-1) ) + (i != NoEntries-1) ) { PagesCount++; } - else if (i == NlsBasePage) - { - // This is NLS data, map it accordingly - // It's VERY important for NT kernel - it calculates size of NLS - // tables based on NlsData memory type descriptors! - - // Firstly map what we already have (if we have any) - // Convert mem types - if (LastPageType == 0) - NtType = LoaderFree; - else if (LastPageType != 0 && LastPageType != 1) - NtType = LoaderFirmwarePermanent; - else if (LastPageType == 1) - NtType = LoaderSystemCode; - else - NtType = LoaderFirmwarePermanent; - - if (PagesCount > 0) - MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, NtType); - - // Then map nls data - MempAddMemoryBlock(LoaderBlock, NlsBasePage, TotalNLSSize, LoaderNlsData); - - // skip them - i += TotalNLSSize; - - // Reset our counter vars - LastPageIndex = i; - LastPageType = MemoryMap[i].PageAllocated; - PagesCount = 1; - - continue; - } else { // Add the resulting region - - // Convert mem types - if (LastPageType == 0) - { - NtType = LoaderFree; - } - else if (LastPageType != 0 && LastPageType != 1) - { - NtType = LoaderFirmwarePermanent; - } - else if (LastPageType == 1) - { - NtType = LoaderSystemCode; - } - else - { - NtType = LoaderFirmwarePermanent; - } - - MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, NtType); + MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, LastPageType); // Reset our counter vars LastPageIndex = i; diff --git a/windows/wlregistry.c b/windows/wlregistry.c index b7737d8adfb..3640a6a8b48 100644 --- a/windows/wlregistry.c +++ b/windows/wlregistry.c @@ -74,8 +74,9 @@ WinLdrLoadSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, } /* Round up the size to page boundary and alloc memory */ - HiveDataPhysical = (ULONG_PTR)MmAllocateMemory( - MM_SIZE_TO_PAGES(HiveFileSize + MM_PAGE_SIZE - 1) << MM_PAGE_SHIFT); + HiveDataPhysical = (ULONG_PTR)MmAllocateMemoryWithType( + MM_SIZE_TO_PAGES(HiveFileSize + MM_PAGE_SIZE - 1) << MM_PAGE_SHIFT, + LoaderRegistryData); if (HiveDataPhysical == 0) { @@ -143,6 +144,14 @@ BOOLEAN WinLdrLoadAndScanSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, // Scan registry and prepare boot drivers list WinLdrScanRegistry(LoaderBlock, DirectoryPath); + // Add boot filesystem driver to the list + //FIXME: Use corresponding driver instead of hardcoding + Status = WinLdrAddDriverToList(&LoaderBlock->BootDriverListHead, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\", + NULL, + L"fastfat"); + + // Get names of NLS files Status = WinLdrGetNLSNames(AnsiName, OemName, LangName); if (!Status) @@ -333,7 +342,7 @@ WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, /* Store it for later marking the pages as NlsData type */ TotalNLSSize = TotalSize; - NlsDataBase = (ULONG_PTR)MmAllocateMemory(TotalSize*MM_PAGE_SIZE); + NlsDataBase = (ULONG_PTR)MmAllocateMemoryWithType(TotalSize*MM_PAGE_SIZE, LoaderNlsData); if (NlsDataBase == 0) goto Failure; @@ -564,7 +573,7 @@ WinLdrScanRegistry(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, DbgPrint((DPRINT_WINDOWS, " Failed to add boot driver\n")); } else { - //DbgPrint((DPRINT_REACTOS, " Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current Tag %d, current group '%S')\n", + //DbgPrint((DPRINT_WINDOWS, " Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current Tag %d, current group '%S')\n", // ServiceName, StartValue, TagValue, DriverGroup, OrderList[TagIndex], GroupName)); } } @@ -639,7 +648,7 @@ WinLdrScanRegistry(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, DbgPrint((DPRINT_WINDOWS, " Failed to add boot driver\n")); } else { - //DbgPrint((DPRINT_REACTOS, " Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current group '%S')\n", + //DbgPrint((DPRINT_WINDOWS, " Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current group '%S')\n", // ServiceName, StartValue, TagValue, DriverGroup, GroupName)); } } @@ -713,9 +722,9 @@ WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead, } // Add registry path - PathLength = wcslen(RegistryPath)*sizeof(WCHAR); + PathLength = (wcslen(RegistryPath)+wcslen(ServiceName))*sizeof(WCHAR); BootDriverEntry->RegistryPath.Length = 0; - BootDriverEntry->RegistryPath.MaximumLength = PathLength+sizeof(WCHAR); + BootDriverEntry->RegistryPath.MaximumLength = PathLength;//+sizeof(WCHAR); BootDriverEntry->RegistryPath.Buffer = MmAllocateMemory(PathLength); if (!BootDriverEntry->RegistryPath.Buffer) return FALSE; @@ -724,8 +733,12 @@ WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead, if (!NT_SUCCESS(Status)) return FALSE; + Status = RtlAppendUnicodeToString(&BootDriverEntry->RegistryPath, ServiceName); + if (!NT_SUCCESS(Status)) + return FALSE; + // Insert entry at top of the list - InsertHeadList(BootDriverListHead, &BootDriverEntry->ListEntry); + InsertTailList(BootDriverListHead, &BootDriverEntry->ListEntry); return TRUE; }