diff --git a/freeldr/freeldr/Makefile b/freeldr/freeldr/Makefile index eff4bf3dbc2..2ca3864d15a 100644 --- a/freeldr/freeldr/Makefile +++ b/freeldr/freeldr/Makefile @@ -209,8 +209,10 @@ ARCH_OBJS = fathelp.o \ i386disk.o \ portio.o \ hardware.o \ + hwcpu.o \ _alloca.o # For Mingw32 builds + RTL_OBJS = print.o \ stdlib.o \ string.o \ diff --git a/freeldr/freeldr/arch/i386/hardware.c b/freeldr/freeldr/arch/i386/hardware.c index 08a9e0f2ff6..3493fd8b6cc 100644 --- a/freeldr/freeldr/arch/i386/hardware.c +++ b/freeldr/freeldr/arch/i386/hardware.c @@ -89,36 +89,6 @@ typedef struct _CM_PNP_BIOS_INSTALLATION_CHECK } __attribute__((packed)) CM_PNP_BIOS_INSTALLATION_CHECK, *PCM_PNP_BIOS_INSTALLATION_CHECK; -typedef struct _MPS_CONFIG_TABLE_HEADER -{ - U32 Signature; - U16 BaseTableLength; - U8 SpecRev; - U8 Checksum; - CHAR OemIdString[8]; - CHAR ProductIdString[12]; - U32 OemTablePointer; - U16 OemTableLength; - U16 EntryCount; - U32 AddressOfLocalAPIC; - U16 ExtendedTableLength; - U8 ExtendedTableChecksum; - U8 Reserved; -} PACKED MPS_CONFIG_TABLE_HEADER, *PMPS_CONFIG_TABLE_HEADER; - - -typedef struct _MPS_PROCESSOR_ENTRY -{ - U8 EntryType; - U8 LocalApicId; - U8 LocalApicVersion; - U8 CpuFlags; - U32 CpuSignature; - U32 FeatureFlags; - U32 Reserved1; - U32 Reserved2; -} PACKED MPS_PROCESSOR_ENTRY, *PMPS_PROCESSOR_ENTRY; - static char Hex[] = "0123456789ABCDEF"; static unsigned int delay_count = 1; @@ -265,6 +235,7 @@ DetectPnpBios(HKEY SystemKey, U32 *BusNumber) { PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; PCM_PNP_BIOS_DEVICE_NODE DeviceNode; + PCM_PNP_BIOS_INSTALLATION_CHECK InstData; char Buffer[80]; HKEY BusKey; U32 x; @@ -278,43 +249,26 @@ DetectPnpBios(HKEY SystemKey, U32 *BusNumber) char *Ptr; S32 Error; - x = PnpBiosSupported((PVOID)DISKREADBUFFER); - if (!x) + InstData = (PCM_PNP_BIOS_INSTALLATION_CHECK)PnpBiosSupported(); + if (InstData == NULL || strncmp(InstData->Signature, "$PnP", 4)) { - printf(" PnP-BIOS not supported\n"); + DbgPrint((DPRINT_HWDETECT, "PnP-BIOS not supported\n")); return; } + DbgPrint((DPRINT_HWDETECT, "Signature '%c%c%c%c'\n", + InstData->Signature[0], InstData->Signature[1], + InstData->Signature[2], InstData->Signature[3])); + x = PnpBiosGetDeviceNodeCount(&NodeSize, &NodeCount); if (x != 0 || NodeSize == 0 || NodeCount == 0) { - DbgPrint((DPRINT_HWDETECT, "PnP-BIOS failed to enumerate device nodes\n"); + DbgPrint((DPRINT_HWDETECT, "PnP-BIOS failed to enumerate device nodes\n")); return; } - DbgPrint((DPRINT_HWDETECT, - "PnP-BIOS supported: found %u device nodes\n", - (unsigned int)NodeCount)); - - FoundNodeCount = 0; - - PnpBufferSize = 0; - for (i = 0; i < 0x255; i++) - { - NodeNumber = (U8)i; - - x = PnpBiosGetDeviceNode(&NodeNumber, (PVOID)DISKREADBUFFER); - if (x == 0) - { - DeviceNode = (PCM_PNP_BIOS_DEVICE_NODE)DISKREADBUFFER; - PnpBufferSize += DeviceNode->Size; - - FoundNodeCount++; - if (FoundNodeCount >= NodeCount) - break; - } - } - PnpBufferSize += sizeof(CM_PNP_BIOS_INSTALLATION_CHECK); - DbgPrint((DPRINT_HWDETECT, "PnpBufferSize: %u\n", PnpBufferSize)); + DbgPrint((DPRINT_HWDETECT, "PnP-BIOS supported\n")); + DbgPrint((DPRINT_HWDETECT, "MaxNodeSize %u NodeCount %u\n", NodeSize, NodeCount)); + DbgPrint((DPRINT_HWDETECT, "Estimated buffer size %u\n", NodeSize * NodeCount)); /* Create new bus key */ sprintf(Buffer, @@ -344,7 +298,7 @@ DetectPnpBios(HKEY SystemKey, U32 *BusNumber) } /* Set 'Configuration Data' value */ - Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + PnpBufferSize; + Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + (NodeSize * NodeCount); FullResourceDescriptor = MmAllocateMemory(Size); if (FullResourceDescriptor == NULL) { @@ -352,9 +306,9 @@ DetectPnpBios(HKEY SystemKey, U32 *BusNumber) "Failed to allocate resource descriptor\n")); return; } + memset(FullResourceDescriptor, 0, Size); /* Initialize resource descriptor */ - memset(FullResourceDescriptor, 0, Size); FullResourceDescriptor->InterfaceType = Internal; FullResourceDescriptor->BusNumber = 0; FullResourceDescriptor->PartialResourceList.Count = 1; @@ -363,19 +317,18 @@ DetectPnpBios(HKEY SystemKey, U32 *BusNumber) FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined; // FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Flags = - FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize = - PnpBufferSize; - Ptr = (char *)((PVOID)FullResourceDescriptor) + sizeof(CM_FULL_RESOURCE_DESCRIPTOR); + Ptr = (char *)(((PVOID)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[0]) + + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); /* Set instalation check data */ - PnpBiosSupported((PVOID)DISKREADBUFFER); - memcpy (Ptr, (PVOID)DISKREADBUFFER, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK)); - - Ptr = (char *)((PVOID)Ptr + sizeof(CM_PNP_BIOS_INSTALLATION_CHECK)); + memcpy (Ptr, InstData, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK)); + Ptr += sizeof(CM_PNP_BIOS_INSTALLATION_CHECK); /* Copy device nodes */ - for (i = 0; i < 0x255; i++) + FoundNodeCount = 0; + PnpBufferSize = sizeof(CM_PNP_BIOS_INSTALLATION_CHECK); + for (i = 0; i < 0xFF; i++) { NodeNumber = (U8)i; @@ -384,10 +337,18 @@ DetectPnpBios(HKEY SystemKey, U32 *BusNumber) { DeviceNode = (PCM_PNP_BIOS_DEVICE_NODE)DISKREADBUFFER; + DbgPrint((DPRINT_HWDETECT, + "Node: %u Size %u (0x%x)\n", + DeviceNode->Node, + DeviceNode->Size, + DeviceNode->Size)); + memcpy (Ptr, DeviceNode, DeviceNode->Size); - Ptr = (char *)((U32)Ptr + DeviceNode->Size); + + Ptr += DeviceNode->Size; + PnpBufferSize += DeviceNode->Size; FoundNodeCount++; if (FoundNodeCount >= NodeCount) @@ -395,6 +356,14 @@ DetectPnpBios(HKEY SystemKey, U32 *BusNumber) } } + /* Set real data size */ + FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize = + PnpBufferSize; + Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + PnpBufferSize; + + DbgPrint((DPRINT_HWDETECT, "Real buffer size: %u\n", PnpBufferSize)); + DbgPrint((DPRINT_HWDETECT, "Resource size: %u\n", Size)); + /* Set 'Configuration Data' value */ Error = RegSetValue(BusKey, "Configuration Data", @@ -411,398 +380,6 @@ DetectPnpBios(HKEY SystemKey, U32 *BusNumber) } -static VOID -DetectCPU(HKEY CpuKey, - HKEY FpuKey) -{ - char VendorIdentifier[13]; - char Identifier[64]; - U32 FeatureSet; - HKEY CpuInstKey; - HKEY FpuInstKey; - U32 eax = 0; - U32 ebx = 0; - U32 ecx = 0; - U32 edx = 0; - U32 *Ptr; - S32 Error; - - /* Create the CPU instance key */ - Error = RegCreateKey(CpuKey, - "0", - &CpuInstKey); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); - return; - } - - /* Create the FPU instance key */ - Error = RegCreateKey(FpuKey, - "0", - &FpuInstKey); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); - return; - } - - eax = CpuidSupported(); - if (eax & 1) - { - DbgPrint((DPRINT_HWDETECT, "CPUID supported\n")); - - /* Get vendor identifier */ - GetCpuid(0, &eax, &ebx, &ecx, &edx); - VendorIdentifier[12] = 0; - Ptr = (U32*)&VendorIdentifier[0]; - *Ptr = ebx; - Ptr++; - *Ptr = edx; - Ptr++; - *Ptr = ecx; - - /* Get Identifier */ - GetCpuid(1, &eax, &ebx, &ecx, &edx); - sprintf(Identifier, - "x86 Family %u Model %u Stepping %u", - (unsigned int)((eax >> 8) & 0x0F), - (unsigned int)((eax >> 4) & 0x0F), - (unsigned int)(eax & 0x0F)); - FeatureSet = edx; - } - else - { - DbgPrint((DPRINT_HWDETECT, "CPUID not supported\n")); - - strcpy(VendorIdentifier, "Unknown"); - sprintf(Identifier, - "x86 Family %u Model %u Stepping %u", - (unsigned int)((eax >> 8) & 0x0F), - (unsigned int)((eax >> 4) & 0x0F), - (unsigned int)(eax & 0x0F)); - FeatureSet = 0; - } - - /* Set 'Conmponent Information' value (CPU and FPU) */ - SetComponentInformation(CpuInstKey, 0, 0, 1); - SetComponentInformation(FpuInstKey, 0, 0, 1); - - /* Set 'FeatureSet' value (CPU only) */ - DbgPrint((DPRINT_HWDETECT, "FeatureSet: %x\n", FeatureSet)); - - Error = RegSetValue(CpuInstKey, - "FeatureSet", - REG_DWORD, - (PU8)&FeatureSet, - sizeof(U32)); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); - } - - /* Set 'Identifier' value (CPU and FPU) */ - DbgPrint((DPRINT_HWDETECT, "Identifier: %s\n", Identifier)); - - Error = RegSetValue(CpuInstKey, - "Identifier", - REG_SZ, - (PU8)Identifier, - strlen(Identifier) + 1); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); - } - - Error = RegSetValue(FpuInstKey, - "Identifier", - REG_SZ, - (PU8)Identifier, - strlen(Identifier) + 1); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); - } - - /* Set 'VendorIdentifier' value (CPU only) */ - DbgPrint((DPRINT_HWDETECT, "Vendor Identifier: %s\n", VendorIdentifier)); - - Error = RegSetValue(CpuInstKey, - "VendorIdentifier", - REG_SZ, - (PU8)VendorIdentifier, - strlen(VendorIdentifier) + 1); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); - } - - /* FIXME: Set 'Update Signature' value (CPU only) */ - - /* FIXME: Set 'Update Status' value (CPU only) */ - - /* FIXME: Set '~MHz' value (CPU only) */ -} - - -static VOID -SetMpsProcessor(HKEY CpuKey, - HKEY FpuKey, - PMPS_PROCESSOR_ENTRY CpuEntry) -{ - char VendorIdentifier[13]; - char Identifier[64]; - char Buffer[8]; - U32 FeatureSet; - HKEY CpuInstKey; - HKEY FpuInstKey; - U32 eax = 0; - U32 ebx = 0; - U32 ecx = 0; - U32 edx = 0; - U32 *Ptr; - S32 Error; - - /* Get processor instance number */ - sprintf(Buffer, "%u", CpuEntry->LocalApicId); - - /* Create the CPU instance key */ - Error = RegCreateKey(CpuKey, - Buffer, - &CpuInstKey); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); - return; - } - - /* Create the FPU instance key */ - Error = RegCreateKey(FpuKey, - Buffer, - &FpuInstKey); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); - return; - } - - /* Get 'VendorIdentifier' */ - GetCpuid(0, &eax, &ebx, &ecx, &edx); - VendorIdentifier[12] = 0; - Ptr = (U32*)&VendorIdentifier[0]; - *Ptr = ebx; - Ptr++; - *Ptr = edx; - Ptr++; - *Ptr = ecx; - - /* Get 'Identifier' */ - sprintf(Identifier, - "x86 Family %u Model %u Stepping %u", - (U32)((CpuEntry->CpuSignature >> 8) & 0x0F), - (U32)((CpuEntry->CpuSignature >> 4) & 0x0F), - (U32)(CpuEntry->CpuSignature & 0x0F)); - - /* Get FeatureSet */ - FeatureSet = CpuEntry->FeatureFlags; - - /* Set 'Configuration Data' value (CPU and FPU) */ - SetComponentInformation(CpuInstKey, - 0, - CpuEntry->LocalApicId, - 1 << CpuEntry->LocalApicId); - - SetComponentInformation(FpuInstKey, - 0, - CpuEntry->LocalApicId, - 1 << CpuEntry->LocalApicId); - - /* Set 'FeatureSet' value (CPU only) */ - DbgPrint((DPRINT_HWDETECT, "FeatureSet: %x\n", FeatureSet)); - - Error = RegSetValue(CpuInstKey, - "FeatureSet", - REG_DWORD, - (PU8)&FeatureSet, - sizeof(U32)); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); - } - - /* Set 'Identifier' value (CPU and FPU) */ - DbgPrint((DPRINT_HWDETECT, "Identifier: %s\n", Identifier)); - - Error = RegSetValue(CpuInstKey, - "Identifier", - REG_SZ, - (PU8)Identifier, - strlen(Identifier) + 1); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); - } - - Error = RegSetValue(FpuInstKey, - "Identifier", - REG_SZ, - (PU8)Identifier, - strlen(Identifier) + 1); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); - } - - /* Set 'VendorIdentifier' value (CPU only) */ - DbgPrint((DPRINT_HWDETECT, "Vendor Identifier: %s\n", VendorIdentifier)); - - Error = RegSetValue(CpuInstKey, - "VendorIdentifier", - REG_SZ, - (PU8)VendorIdentifier, - strlen(VendorIdentifier) + 1); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); - } - - /* FIXME: Set 'Update Signature' value (CPU only) */ - - /* FIXME: Set 'Update Status' value (CPU only) */ - - /* FIXME: Set '~MHz' value (CPU only) */ -} - - -static BOOL -DetectMps(HKEY CpuKey, - HKEY FpuKey) -{ - PMPS_CONFIG_TABLE_HEADER ConfigTable; - PMPS_PROCESSOR_ENTRY CpuEntry; - U32 DefaultConfig; - char *Buffer; - char *Ptr; - U32 Offset; - - DefaultConfig = MpsGetDefaultConfiguration(); - if (DefaultConfig == 0) - { - /* Read configuration table */ - MpsGetConfigurationTable((PVOID)DISKREADBUFFER); - Buffer = (char *)DISKREADBUFFER; - DbgPrint((DPRINT_HWDETECT, "MPS signature: %c%c%c%c\n", - Buffer[0], Buffer[1], Buffer[2], Buffer[3])); - - ConfigTable = (PMPS_CONFIG_TABLE_HEADER)DISKREADBUFFER; - Offset = 0x2C; - while (Offset < ConfigTable->BaseTableLength) - { - Ptr = Buffer + Offset; - - switch (*Ptr) - { - case 0: - CpuEntry = (PMPS_PROCESSOR_ENTRY)Ptr; - - DbgPrint((DPRINT_HWDETECT, "Processor Entry\n")); - DbgPrint((DPRINT_HWDETECT, - "APIC Id %u APIC Version %u Flags %x Signature %x Feature %x\n", - CpuEntry->LocalApicId, - CpuEntry->LocalApicVersion, - CpuEntry->CpuFlags, - CpuEntry->CpuSignature, - CpuEntry->FeatureFlags)); - DbgPrint((DPRINT_HWDETECT, - "Processor %u: x86 Family %u Model %u Stepping %u\n", - CpuEntry->LocalApicId, - (U32)((CpuEntry->CpuSignature >> 8) & 0x0F), - (U32)((CpuEntry->CpuSignature >> 4) & 0x0F), - (U32)(CpuEntry->CpuSignature & 0x0F))); - - SetMpsProcessor(CpuKey, FpuKey, CpuEntry); - Offset += 0x14; - break; - - case 1: - DbgPrint((DPRINT_HWDETECT, "Bus Entry\n")); - Offset += 0x08; - break; - - case 2: - DbgPrint((DPRINT_HWDETECT, "I/0 APIC Entry\n")); - Offset += 0x08; - break; - - case 3: - DbgPrint((DPRINT_HWDETECT, "I/0 Interrupt Assignment Entry\n")); - Offset += 0x08; - break; - - case 4: - DbgPrint((DPRINT_HWDETECT, "Local Interrupt Assignment Entry\n")); - Offset += 0x08; - break; - - default: - DbgPrint((DPRINT_HWDETECT, "Unknown Entry %u\n",(U32)*Ptr)); - return FALSE; - } - - } - } - else - { - DbgPrint((DPRINT_HWDETECT, - "Unsupported MPS configuration: %x\n", - (U32)DefaultConfig)); - - /* FIXME: Identify default configurations */ - - return FALSE; - } - - return TRUE; -} - - -static VOID -DetectCPUs(HKEY SystemKey) -{ - HKEY CpuKey; - HKEY FpuKey; - S32 Error; - - /* Create the 'CentralProcessor' key */ - Error = RegCreateKey(SystemKey, - "CentralProcessor", - &CpuKey); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); - return; - } - - /* Create the 'FloatingPointProcessor' key */ - Error = RegCreateKey(SystemKey, - "FloatingPointProcessor", - &FpuKey); - if (Error != ERROR_SUCCESS) - { - DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); - return; - } - - if (MpsSupported()) - { - DetectMps(CpuKey, FpuKey); - } - else - { - DetectCPU(CpuKey, FpuKey); - } -} - static VOID SetHarddiskConfigurationData(HKEY DiskKey, diff --git a/freeldr/freeldr/arch/i386/hardware.h b/freeldr/freeldr/arch/i386/hardware.h index 1291540a08c..b2e4f9fece3 100644 --- a/freeldr/freeldr/arch/i386/hardware.h +++ b/freeldr/freeldr/arch/i386/hardware.h @@ -150,6 +150,7 @@ VOID SetComponentInformation(HKEY ComponentKey, U32 Affinity); /* hwcpu.c */ +VOID DetectCPUs(HKEY SystemKey); /* i386cpu.S */ U32 CpuidSupported(VOID); @@ -159,13 +160,8 @@ VOID GetCpuid(U32 Level, U32 *ecx, U32 *edx); -U32 MpsSupported(VOID); -U32 MpsGetDefaultConfiguration(VOID); -U32 MpsGetConfigurationTable(PVOID ConfigTable); - /* i386pnp.S */ -//U32 PnpBiosSupported(VOID); -U32 PnpBiosSupported(PVOID InstallationCheck); +U32 PnpBiosSupported(VOID); U32 PnpBiosGetDeviceNodeCount(U32 *NodeSize, U32 *NodeCount); U32 PnpBiosGetDeviceNode(U8 *NodeId, diff --git a/freeldr/freeldr/arch/i386/hwcpu.c b/freeldr/freeldr/arch/i386/hwcpu.c new file mode 100644 index 00000000000..85969e6362d --- /dev/null +++ b/freeldr/freeldr/arch/i386/hwcpu.c @@ -0,0 +1,571 @@ +/* + * FreeLoader + * + * Copyright (C) 2003 Eric Kohl + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "../../reactos/registry.h" +#include "hardware.h" + + +#define MP_FP_SIGNATURE 0x5F504D5F /* "_MP_" */ +#define MP_CT_SIGNATURE 0x504D4350 /* "_MP_" */ + + +typedef struct _MP_FLOATING_POINT_TABLE +{ + U32 Signature; /* "_MP_" */ + U32 PhysicalAddressPointer; + U8 Length; + U8 SpecRev; + U8 Checksum; + U8 FeatureByte[5]; +} PACKED MP_FLOATING_POINT_TABLE, *PMP_FLOATING_POINT_TABLE; + + +typedef struct _MPS_CONFIG_TABLE_HEADER +{ + U32 Signature; /* "PCMP" */ + U16 BaseTableLength; + U8 SpecRev; + U8 Checksum; + U8 OemIdString[8]; + U8 ProductIdString[12]; + U32 OemTablePointer; + U16 OemTableLength; + U16 EntryCount; + U32 AddressOfLocalAPIC; + U16 ExtendedTableLength; + U8 ExtendedTableChecksum; + U8 Reserved; +} PACKED MP_CONFIGURATION_TABLE, *PMP_CONFIGURATION_TABLE; + + +typedef struct _MP_PROCESSOR_ENTRY +{ + U8 EntryType; + U8 LocalApicId; + U8 LocalApicVersion; + U8 CpuFlags; + U32 CpuSignature; + U32 FeatureFlags; + U32 Reserved1; + U32 Reserved2; +} PACKED MP_PROCESSOR_ENTRY, *PMP_PROCESSOR_ENTRY; + + +/* FUNCTIONS ****************************************************************/ + +static VOID +DetectCPU(HKEY CpuKey, + HKEY FpuKey) +{ + char VendorIdentifier[13]; + char Identifier[64]; + U32 FeatureSet; + HKEY CpuInstKey; + HKEY FpuInstKey; + U32 eax = 0; + U32 ebx = 0; + U32 ecx = 0; + U32 edx = 0; + U32 *Ptr; + S32 Error; + + /* Create the CPU instance key */ + Error = RegCreateKey(CpuKey, + "0", + &CpuInstKey); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); + return; + } + + /* Create the FPU instance key */ + Error = RegCreateKey(FpuKey, + "0", + &FpuInstKey); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); + return; + } + + eax = CpuidSupported(); + if (eax & 1) + { + DbgPrint((DPRINT_HWDETECT, "CPUID supported\n")); + + /* Get vendor identifier */ + GetCpuid(0, &eax, &ebx, &ecx, &edx); + VendorIdentifier[12] = 0; + Ptr = (U32*)&VendorIdentifier[0]; + *Ptr = ebx; + Ptr++; + *Ptr = edx; + Ptr++; + *Ptr = ecx; + + /* Get Identifier */ + GetCpuid(1, &eax, &ebx, &ecx, &edx); + sprintf(Identifier, + "x86 Family %u Model %u Stepping %u", + (unsigned int)((eax >> 8) & 0x0F), + (unsigned int)((eax >> 4) & 0x0F), + (unsigned int)(eax & 0x0F)); + FeatureSet = edx; + } + else + { + DbgPrint((DPRINT_HWDETECT, "CPUID not supported\n")); + + strcpy(VendorIdentifier, "Unknown"); + sprintf(Identifier, + "x86 Family %u Model %u Stepping %u", + (unsigned int)((eax >> 8) & 0x0F), + (unsigned int)((eax >> 4) & 0x0F), + (unsigned int)(eax & 0x0F)); + FeatureSet = 0; + } + + /* Set 'Conmponent Information' value (CPU and FPU) */ + SetComponentInformation(CpuInstKey, 0, 0, 1); + SetComponentInformation(FpuInstKey, 0, 0, 1); + + /* Set 'FeatureSet' value (CPU only) */ + DbgPrint((DPRINT_HWDETECT, "FeatureSet: %x\n", FeatureSet)); + + Error = RegSetValue(CpuInstKey, + "FeatureSet", + REG_DWORD, + (PU8)&FeatureSet, + sizeof(U32)); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); + } + + /* Set 'Identifier' value (CPU and FPU) */ + DbgPrint((DPRINT_HWDETECT, "Identifier: %s\n", Identifier)); + + Error = RegSetValue(CpuInstKey, + "Identifier", + REG_SZ, + (PU8)Identifier, + strlen(Identifier) + 1); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); + } + + Error = RegSetValue(FpuInstKey, + "Identifier", + REG_SZ, + (PU8)Identifier, + strlen(Identifier) + 1); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); + } + + /* Set 'VendorIdentifier' value (CPU only) */ + DbgPrint((DPRINT_HWDETECT, "Vendor Identifier: %s\n", VendorIdentifier)); + + Error = RegSetValue(CpuInstKey, + "VendorIdentifier", + REG_SZ, + (PU8)VendorIdentifier, + strlen(VendorIdentifier) + 1); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); + } + + /* FIXME: Set 'Update Signature' value (CPU only) */ + + /* FIXME: Set 'Update Status' value (CPU only) */ + + /* FIXME: Set '~MHz' value (CPU only) */ +} + + +static VOID +SetMpsProcessor(HKEY CpuKey, + HKEY FpuKey, + PMP_PROCESSOR_ENTRY CpuEntry) +{ + char VendorIdentifier[13]; + char Identifier[64]; + char Buffer[8]; + U32 FeatureSet; + HKEY CpuInstKey; + HKEY FpuInstKey; + U32 eax = 0; + U32 ebx = 0; + U32 ecx = 0; + U32 edx = 0; + U32 *Ptr; + S32 Error; + + /* Get processor instance number */ + sprintf(Buffer, "%u", CpuEntry->LocalApicId); + + /* Create the CPU instance key */ + Error = RegCreateKey(CpuKey, + Buffer, + &CpuInstKey); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); + return; + } + + /* Create the FPU instance key */ + Error = RegCreateKey(FpuKey, + Buffer, + &FpuInstKey); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); + return; + } + + /* Get 'VendorIdentifier' */ + GetCpuid(0, &eax, &ebx, &ecx, &edx); + VendorIdentifier[12] = 0; + Ptr = (U32*)&VendorIdentifier[0]; + *Ptr = ebx; + Ptr++; + *Ptr = edx; + Ptr++; + *Ptr = ecx; + + /* Get 'Identifier' */ + sprintf(Identifier, + "x86 Family %u Model %u Stepping %u", + (U32)((CpuEntry->CpuSignature >> 8) & 0x0F), + (U32)((CpuEntry->CpuSignature >> 4) & 0x0F), + (U32)(CpuEntry->CpuSignature & 0x0F)); + + /* Get FeatureSet */ + FeatureSet = CpuEntry->FeatureFlags; + + /* Set 'Configuration Data' value (CPU and FPU) */ + SetComponentInformation(CpuInstKey, + 0, + CpuEntry->LocalApicId, + 1 << CpuEntry->LocalApicId); + + SetComponentInformation(FpuInstKey, + 0, + CpuEntry->LocalApicId, + 1 << CpuEntry->LocalApicId); + + /* Set 'FeatureSet' value (CPU only) */ + DbgPrint((DPRINT_HWDETECT, "FeatureSet: %x\n", FeatureSet)); + + Error = RegSetValue(CpuInstKey, + "FeatureSet", + REG_DWORD, + (PU8)&FeatureSet, + sizeof(U32)); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); + } + + /* Set 'Identifier' value (CPU and FPU) */ + DbgPrint((DPRINT_HWDETECT, "Identifier: %s\n", Identifier)); + + Error = RegSetValue(CpuInstKey, + "Identifier", + REG_SZ, + (PU8)Identifier, + strlen(Identifier) + 1); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); + } + + Error = RegSetValue(FpuInstKey, + "Identifier", + REG_SZ, + (PU8)Identifier, + strlen(Identifier) + 1); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); + } + + /* Set 'VendorIdentifier' value (CPU only) */ + DbgPrint((DPRINT_HWDETECT, "Vendor Identifier: %s\n", VendorIdentifier)); + + Error = RegSetValue(CpuInstKey, + "VendorIdentifier", + REG_SZ, + (PU8)VendorIdentifier, + strlen(VendorIdentifier) + 1); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); + } + + /* FIXME: Set 'Update Signature' value (CPU only) */ + + /* FIXME: Set 'Update Status' value (CPU only) */ + + /* FIXME: Set '~MHz' value (CPU only) */ +} + + +static PMP_FLOATING_POINT_TABLE +GetMpFloatingPointTable(VOID) +{ + PMP_FLOATING_POINT_TABLE FpTable; + char *Ptr; + U8 Sum; + U32 Length; + U32 i; + + FpTable = (PMP_FLOATING_POINT_TABLE)0xF0000; + while ((U32)FpTable < 0x100000) + { + if (FpTable->Signature == MP_FP_SIGNATURE) + { + Length = FpTable->Length * 0x10; + Ptr = (char *)FpTable; + Sum = 0; + for (i = 0; i < Length; i++) + { + Sum += Ptr[i]; + } + DbgPrint((DPRINT_HWDETECT, + "Checksum: %u\n", + Sum)); + + if (Sum != 0) + { + DbgPrint((DPRINT_HWDETECT, + "Invalid MP floating point checksum: %u\n", + Sum)); + return NULL; + } + + return FpTable; + } + + FpTable = (PMP_FLOATING_POINT_TABLE)((U32)FpTable + 0x10); + } + + return NULL; +} + + +static PMP_CONFIGURATION_TABLE +GetMpConfigurationTable(PMP_FLOATING_POINT_TABLE FpTable) +{ + PMP_CONFIGURATION_TABLE ConfigTable; + char *Ptr; + U8 Sum; + U32 Length; + U32 i; + + if (FpTable->FeatureByte[0] != 0 || + FpTable->PhysicalAddressPointer == 0) + return NULL; + + ConfigTable = (PMP_CONFIGURATION_TABLE)FpTable->PhysicalAddressPointer; + if (ConfigTable->Signature != MP_CT_SIGNATURE) + return NULL; + + DbgPrint((DPRINT_HWDETECT, + "MP Configuration Table at: %x\n", + (U32)ConfigTable)); + + /* Calculate base table checksum */ + Length = ConfigTable->BaseTableLength; + Ptr = (char *)ConfigTable; + Sum = 0; + for (i = 0; i < Length; i++) + { + Sum += Ptr[i]; + } + DbgPrint((DPRINT_HWDETECT, + "MP Configuration Table base checksum: %u\n", + Sum)); + + if (Sum != 0) + { + DbgPrint((DPRINT_HWDETECT, + "Invalid MP Configuration Table base checksum: %u\n", + Sum)); + return NULL; + } + + if (ConfigTable->ExtendedTableLength != 0) + { + /* FIXME: Check extended table */ + } + + return ConfigTable; +} + + +static BOOL +DetectMps(HKEY CpuKey, + HKEY FpuKey) +{ + PMP_FLOATING_POINT_TABLE FpTable; + PMP_CONFIGURATION_TABLE ConfigTable; + PMP_PROCESSOR_ENTRY CpuEntry; + char *Ptr; + U32 Offset; + + /* Get floating point table */ + FpTable = GetMpFloatingPointTable(); + if (FpTable == NULL) + return FALSE; + + DbgPrint((DPRINT_HWDETECT, + "MP Floating Point Table at: %x\n", + (U32)FpTable)); + + if (FpTable->FeatureByte[0] == 0) + { + /* Get configuration table */ + ConfigTable = GetMpConfigurationTable(FpTable); + if (ConfigTable == NULL) + { + DbgPrint((DPRINT_HWDETECT, + "Failed to find the MP Configuration Table\n")); + return FALSE; + } + + Offset = sizeof(MP_CONFIGURATION_TABLE); + while (Offset < ConfigTable->BaseTableLength) + { + Ptr = (char*)((U32)ConfigTable + Offset); + + switch (*Ptr) + { + case 0: + CpuEntry = (PMP_PROCESSOR_ENTRY)Ptr; + + DbgPrint((DPRINT_HWDETECT, "Processor Entry\n")); + DbgPrint((DPRINT_HWDETECT, + "APIC Id %u APIC Version %u Flags %x Signature %x Feature %x\n", + CpuEntry->LocalApicId, + CpuEntry->LocalApicVersion, + CpuEntry->CpuFlags, + CpuEntry->CpuSignature, + CpuEntry->FeatureFlags)); + DbgPrint((DPRINT_HWDETECT, + "Processor %u: x86 Family %u Model %u Stepping %u\n", + CpuEntry->LocalApicId, + (U32)((CpuEntry->CpuSignature >> 8) & 0x0F), + (U32)((CpuEntry->CpuSignature >> 4) & 0x0F), + (U32)(CpuEntry->CpuSignature & 0x0F))); + + SetMpsProcessor(CpuKey, FpuKey, CpuEntry); + Offset += 0x14; + break; + + case 1: + DbgPrint((DPRINT_HWDETECT, "Bus Entry\n")); + Offset += 0x08; + break; + + case 2: + DbgPrint((DPRINT_HWDETECT, "I/0 APIC Entry\n")); + Offset += 0x08; + break; + + case 3: + DbgPrint((DPRINT_HWDETECT, "I/0 Interrupt Assignment Entry\n")); + Offset += 0x08; + break; + + case 4: + DbgPrint((DPRINT_HWDETECT, "Local Interrupt Assignment Entry\n")); + Offset += 0x08; + break; + + default: + DbgPrint((DPRINT_HWDETECT, "Unknown Entry %u\n",(U32)*Ptr)); + return FALSE; + } + } + } + else + { + DbgPrint((DPRINT_HWDETECT, + "Unsupported MPS configuration: %x\n", + FpTable->FeatureByte[0])); + + /* FIXME: Identify default configurations */ + + return FALSE; + } + + return TRUE; +} + + + +VOID +DetectCPUs(HKEY SystemKey) +{ + HKEY CpuKey; + HKEY FpuKey; + S32 Error; + + /* Create the 'CentralProcessor' key */ + Error = RegCreateKey(SystemKey, + "CentralProcessor", + &CpuKey); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); + return; + } + + /* Create the 'FloatingPointProcessor' key */ + Error = RegCreateKey(SystemKey, + "FloatingPointProcessor", + &FpuKey); + if (Error != ERROR_SUCCESS) + { + DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error)); + return; + } + + /* Detect CPUs */ + if (!DetectMps(CpuKey, FpuKey)) + { + DetectCPU(CpuKey, FpuKey); + } +} + +/* EOF */ diff --git a/freeldr/freeldr/arch/i386/i386cpu.S b/freeldr/freeldr/arch/i386/i386cpu.S index 26bb9e7b862..7060ef2a392 100644 --- a/freeldr/freeldr/arch/i386/i386cpu.S +++ b/freeldr/freeldr/arch/i386/i386cpu.S @@ -93,6 +93,7 @@ EXTERN(_GetCpuid) pushl %esi movl 0x08(%ebp),%eax + cpuid movl 0x0C(%ebp),%esi @@ -117,227 +118,4 @@ EXTERN(_GetCpuid) popl %ebp ret -/* - * U32 MpsSupported(VOID); - * - * RETURNS: - */ - - .code16 -_mps_supported: - .long 0 -_mps_fp_table_offset: - .word 0 - -EXTERN(_MpsSupported) - .code32 - - pushl %ebp - movl %esp,%ebp - pushal - push %es - - call switch_to_real - - .code16 - - /* init ES */ - pushw $0xF000 - popw %es - - /* init SI */ - movw $0xFFF0,%si - -mps_again: - movw %es:(%si),%ax - cmp $0x4D5F,%ax /* "_M" */ - jne mps_next - - push %si - add $2,%si - movw %es:(%si),%ax - cmp $0x5F50,%ax /* "P_" */ - pop %si - je mps_found - -mps_next: - cmp $0,%si - je mps_not_found - - sub $0x10,%si - jmp mps_again - -mps_found: - movw %si,_mps_fp_table_offset - movzwl %si,%eax - movl %eax,_mps_supported - -mps_not_found: - call switch_to_prot - - .code32 - - pop %es - popal - movl %ebp,%esp - popl %ebp - - movl _mps_supported,%eax - - ret - - -/* - * U32 MpsGetDefaultConfiguration(VOID); - * - * RETURNS: - */ - .code16 -_mps_default_configuration: - .long 0 - -EXTERN(_MpsGetDefaultConfiguration) - .code32 - - pushl %ebp - movl %esp,%ebp - pushal - push %es - - call switch_to_real - - .code16 - - /* init ES */ - pushw $0xF000 - popw %es - - /* init SI */ - movw _mps_fp_table_offset,%si - - /* read default configuration (feature byte 1) */ - addw $0x0B,%si - movb %es:(%si),%al - - /* save configuration */ - movzbl %al,%ecx - movl %ecx,_mps_default_configuration - - call switch_to_prot - - .code32 - - pop %es - popal - movl %ebp,%esp - popl %ebp - - movl _mps_default_configuration,%eax - - ret - - -/* - * U32 MpsGetConfigurationTable(PVOID ConfigTable); - * - * RETURNS: - */ - .code16 -_mps_buffer_segment: - .word 0 -_mps_buffer_offset: - .word 0 - -_mps_config_segment: - .word 0 -_mps_config_offset: - .word 0 -_mps_config_length: - .word 0 - -EXTERN(_MpsGetConfigurationTable) - .code32 - - pushl %ebp - movl %esp,%ebp - pushal - push %es - - /* convert pointer to node buffer to segment/offset */ - movl 0x08(%ebp),%eax - shrl $4,%eax - andl $0xf000,%eax - movw %ax,_mps_buffer_segment - movl 0x08(%ebp),%eax - andl $0xffff,%eax - movw %ax,_mps_buffer_offset - - call switch_to_real - - .code16 - - /* init ES */ - pushw $0xF000 - popw %es - - /* init SI */ - movw _mps_fp_table_offset,%si - - /* read pointer to configuration table */ - addw $0x04,%si - movl %es:(%si),%eax - - /* save table offset */ - movw %ax,_mps_config_offset - - /* save table segment */ - shrl $0x4,%eax - andw $0xf000,%ax - movw %ax,_mps_config_segment - - /* init ES */ - pushw _mps_config_segment - popw %es - - /* init CX (read table lenght) */ - movw _mps_config_offset,%si - addw $0x04,%si - movw %es:(%si),%cx - - /* init ES */ - pushw _mps_buffer_segment - popw %es - - /* init DI */ - movw _mps_buffer_offset,%di - - /* init SI */ - movw _mps_config_offset,%si - - /* init DS */ -.code32 - movw _mps_config_segment,%ax -.code16 - pushw %ds - pushw %ax - popw %ds - - /* copy table */ -// cld - rep movsb - - /* restore DS */ - pop %ds - - call switch_to_prot - - .code32 - - pop %es - popal - movl %ebp,%esp - popl %ebp - - ret - /* EOF */ diff --git a/freeldr/freeldr/arch/i386/i386pnp.S b/freeldr/freeldr/arch/i386/i386pnp.S index be02af4b2fa..67bc29bfed8 100644 --- a/freeldr/freeldr/arch/i386/i386pnp.S +++ b/freeldr/freeldr/arch/i386/i386pnp.S @@ -26,101 +26,56 @@ /* - * U32 PnpBiosSupported(PVOID InstallationCheck); + * U32 PnpBiosSupported(VOID); * * RETURNS: */ -_pnp_support_result: +_pnp_bios_entry_point: .long 0 -_pnp_entry_point: - .word 0 -_pnp_code_segment: - .word 0 -_pnp_data_segment: +_pnp_bios_data_segment: .word 0 EXTERN(_PnpBiosSupported) .code32 - pushal - push %es + pushl %edi + pushl %esi - /* convert pointer to node buffer to segment/offset */ - movl 0x08(%ebp),%eax - shrl $4,%eax - andl $0xf000,%eax - movw %ax,_pnp_buffer_segment - movl 0x08(%ebp),%eax - andl $0xffff,%eax - movw %ax,_pnp_buffer_offset + xorl %edi,%edi - call switch_to_real - - .code16 - - /* init ES */ - pushw $0xF000 - popw %es - - /* init cx */ - movw $0xFFF0,%si + /* init esi */ + movl $0xFFFF0,%esi pnp_again: - movw %es:(%si),%ax - cmp $0x5024,%ax /* "$P" */ - jne pnp_next - - push %si - add $2,%si - movw %es:(%si),%ax - cmp $0x506E,%ax /* "nP" */ - pop %si + movl (%esi),%eax + cmp $0x506E5024,%eax /* "$PnP" */ je pnp_found -pnp_next: - cmp $0,%si + cmp $0xF0000,%esi je pnp_not_found - sub $0x10,%si + subl $0x10,%esi jmp pnp_again pnp_found: - movzwl %si,%eax - movl %eax,_pnp_support_result + movl %esi,%edi - add $0x0D,%si - movw %es:(%si),%ax - movw %ax,_pnp_entry_point + /* Calculate the bios entry point (far pointer) */ + xorl %eax,%eax + movw 0x0F(%esi),%ax + shll $16,%eax + movw 0x0D(%esi),%ax + movl %eax,_pnp_bios_entry_point - add $0x02,%si - movw %es:(%si),%ax - movw %ax,_pnp_code_segment + /* Store bios data segment */ + movw 0x1B(%esi),%ax + movw %ax,_pnp_bios_data_segment - add $0x0C,%si - movw %es:(%si),%ax - movw %ax,_pnp_data_segment - - /* copy data to buffer */ - push %ds - movw %es, %ax - movw %ax, %ds - movl _pnp_support_result, %esi - movw _pnp_buffer_segment, %es - movw _pnp_buffer_offset, %di - movw $0x21, %cx - rep movsb - - pop %ds pnp_not_found: + movl %edi,%eax - call switch_to_prot - - .code32 - - pop %es - popal - - movl _pnp_support_result,%eax + popl %esi + popl %edi ret @@ -130,7 +85,7 @@ pnp_not_found: * * RETURNS: */ -_entry_point: +_pnp_result: .long 0 _pnp_node_size: .word 0 @@ -147,10 +102,9 @@ EXTERN(_PnpBiosGetDeviceNodeCount) push %es call switch_to_real - .code16 - movw _pnp_data_segment,%ax + movw _pnp_bios_data_segment,%ax pushw %ax pushw %cs @@ -163,23 +117,14 @@ EXTERN(_PnpBiosGetDeviceNodeCount) pushw $0 - movw _pnp_code_segment,%ax - movzwl %ax,%ecx - shll $16,%ecx - movw _pnp_entry_point,%ax - movzwl %ax,%ebx - orl %ebx,%ecx - movl %ecx,_entry_point - - lcall *_entry_point + lcall *_pnp_bios_entry_point addw $12,%sp movzwl %ax,%ecx - movl %ecx,_pnp_support_result + movl %ecx,_pnp_result call switch_to_prot - .code32 movl 0x08(%ebp),%esi @@ -198,7 +143,7 @@ EXTERN(_PnpBiosGetDeviceNodeCount) movl %ebp,%esp popl %ebp - movl _pnp_support_result,%eax + movl _pnp_result,%eax ret @@ -216,7 +161,6 @@ _pnp_buffer_offset: _pnp_node_number: .byte 0 - EXTERN(_PnpBiosGetDeviceNode) .code32 @@ -241,11 +185,10 @@ EXTERN(_PnpBiosGetDeviceNode) movw %ax,_pnp_buffer_offset call switch_to_real - .code16 /* push bios segment */ - movw _pnp_data_segment,%ax + movw _pnp_bios_data_segment,%ax pushw %ax /* push control flag */ @@ -266,31 +209,27 @@ EXTERN(_PnpBiosGetDeviceNode) pushw $1 /* call entry point */ - lcall *_entry_point + lcall *_pnp_bios_entry_point addw $14,%sp movzwl %ax,%ecx - movl %ecx,_pnp_support_result - + movl %ecx,_pnp_result call switch_to_prot - .code32 - /* update node number */ movl 0x08(%ebp),%esi movb _pnp_node_number,%al movb %al,(%esi) - pop %es popal movl %ebp,%esp popl %ebp - movl _pnp_support_result,%eax + movl _pnp_result,%eax ret