u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset) { u32 v; __outdword(PCI_CONFIG_ADDRESS, 0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset); v = __indword(PCI_CONFIG_DATA); return v; }
// Perform IO instruction according with parameters _Use_decl_annotations_ static void VmmpIoWrapper(bool to_memory, bool is_string, SIZE_T size_of_access, unsigned short port, void *address, unsigned long count) { NT_ASSERT(size_of_access == 1 || size_of_access == 2 || size_of_access == 4); // Update CR3 with that of the guest since below code is going to access // memory. const auto guest_cr3 = UtilVmRead(VmcsField::kGuestCr3); const auto vmm_cr3 = __readcr3(); __writecr3(guest_cr3); // clang-format off if (to_memory) { if (is_string) { // IN switch (size_of_access) { case 1: *reinterpret_cast<UCHAR*>(address) = __inbyte(port); break; case 2: *reinterpret_cast<USHORT*>(address) = __inword(port); break; case 4: *reinterpret_cast<ULONG*>(address) = __indword(port); break; } } else { // INS switch (size_of_access) { case 1: __inbytestring(port, reinterpret_cast<UCHAR*>(address), count); break; case 2: __inwordstring(port, reinterpret_cast<USHORT*>(address), count); break; case 4: __indwordstring(port, reinterpret_cast<ULONG*>(address), count); break; } } } else { if (is_string) { // OUT switch (size_of_access) { case 1: __outbyte(port, *reinterpret_cast<UCHAR*>(address)); break; case 2: __outword(port, *reinterpret_cast<USHORT*>(address)); break; case 4: __outdword(port, *reinterpret_cast<ULONG*>(address)); break; } } else { // OUTS switch (size_of_access) { case 1: __outbytestring(port, reinterpret_cast<UCHAR*>(address), count); break; case 2: __outwordstring(port, reinterpret_cast<USHORT*>(address), count); break; case 4: __outdwordstring(port, reinterpret_cast<ULONG*>(address), count); break; } } } // clang-format on __writecr3(vmm_cr3); }
NTSTATUS __fastcall DispatchIOCTL(IN PIOCTL_INFO RequestInfo, OUT PULONG ResponseLength) { NTSTATUS Status = STATUS_SUCCESS; #define INPUT(Type) ((Type)(RequestInfo->InputBuffer)) #define OUTPUT(Type) ((Type)(RequestInfo->OutputBuffer)) #define SET_RESPONSE_LENGTH(Length) if (ResponseLength != NULL) {*ResponseLength = (Length);} switch (RequestInfo->ControlCode) { // DriverFunctions: case GET_HANDLES_COUNT: *OUTPUT(PULONG) = GetHandlesCount(); SET_RESPONSE_LENGTH(sizeof(ULONG)); break; // NativeFunctions: case START_BEEPER: __outbyte(0x61, __inbyte(0x61) | 3); break; case STOP_BEEPER: __outbyte(0x61, __inbyte(0x61) & 252); break; case SET_BEEPER_REGIME: __outbyte(0x43, 0xB6); break; case SET_BEEPER_OUT: __outbyte(0x61, __inbyte(0x61) | 2); break; case SET_BEEPER_IN: __outbyte(0x61, __inbyte(0x61) & 253); break; case SET_BEEPER_DIVIDER: SetBeeperDivider(*INPUT(PWORD)); break; case SET_BEEPER_FREQUENCY: SetBeeperFrequency(*INPUT(PWORD)); break; case READ_IO_PORT_BYTE: *OUTPUT(PBYTE) = __inbyte(*INPUT(PWORD)); SET_RESPONSE_LENGTH(sizeof(BYTE)); break; case READ_IO_PORT_WORD: *OUTPUT(PWORD) = __inword(*INPUT(PWORD)); SET_RESPONSE_LENGTH(sizeof(WORD)); break; case READ_IO_PORT_DWORD: *OUTPUT(PDWORD32) = __indword(*INPUT(PWORD)); SET_RESPONSE_LENGTH(sizeof(DWORD)); break; case WRITE_IO_PORT_BYTE: __outbyte( INPUT(PWRITE_IO_PORT_BYTE_INPUT)->PortNumber, INPUT(PWRITE_IO_PORT_BYTE_INPUT)->Data ); break; case WRITE_IO_PORT_WORD: __outword( INPUT(PWRITE_IO_PORT_WORD_INPUT)->PortNumber, INPUT(PWRITE_IO_PORT_WORD_INPUT)->Data ); break; case WRITE_IO_PORT_DWORD: __outdword( INPUT(PWRITE_IO_PORT_DWORD_INPUT)->PortNumber, INPUT(PWRITE_IO_PORT_DWORD_INPUT)->Data ); break; case RDPMC: *OUTPUT(PULONGLONG) = __readpmc(*INPUT(PULONG)); SET_RESPONSE_LENGTH(sizeof(ULONGLONG)); break; case RDMSR: *OUTPUT(PULONGLONG) = __readmsr(*INPUT(PULONG)); SET_RESPONSE_LENGTH(sizeof(ULONGLONG)); break; case WRMSR: __writemsr(INPUT(PWRMSR_INPUT)->Index, INPUT(PWRMSR_INPUT)->Data); break; // MemoryUtils: case ALLOC_KERNEL_MEMORY: *OUTPUT(PUINT64) = (SIZE_T)GetMem(*INPUT(PSIZE_T)); SET_RESPONSE_LENGTH(sizeof(UINT64)); break; case FREE_KERNEL_MEMORY: FreeMem((PVOID)*INPUT(PUINT64)); break; case COPY_MEMORY: RtlCopyMemory( (PVOID)INPUT(PCOPY_MEMORY_INPUT)->Destination, (PVOID)INPUT(PCOPY_MEMORY_INPUT)->Source, (SIZE_T)INPUT(PCOPY_MEMORY_INPUT)->Size ); break; case FILL_MEMORY: RtlFillMemory( (PVOID)INPUT(PFILL_MEMORY_INPUT)->Destination, (SIZE_T)INPUT(PFILL_MEMORY_INPUT)->Size, (BYTE)INPUT(PFILL_MEMORY_INPUT)->FillingByte ); break; case ALLOC_PHYSICAL_MEMORY: *OUTPUT(PUINT64) = (SIZE_T)AllocPhysicalMemory( INPUT(PALLOC_PHYSICAL_MEMORY_INPUT)->PhysicalAddress, (SIZE_T)INPUT(PALLOC_PHYSICAL_MEMORY_INPUT)->Size ); SET_RESPONSE_LENGTH(sizeof(UINT64)); break; case FREE_PHYSICAL_MEMORY: FreePhysicalMemory((PVOID)*INPUT(PUINT64)); break; case GET_PHYSICAL_ADDRESS: *OUTPUT(PPHYSICAL_ADDRESS) = GetPhysicalAddressInProcess( (HANDLE)INPUT(PGET_PHYSICAL_ADDRESS_INPUT)->ProcessID, (PVOID)INPUT(PGET_PHYSICAL_ADDRESS_INPUT)->VirtualAddress ); SET_RESPONSE_LENGTH(sizeof(PHYSICAL_ADDRESS)); break; case READ_PHYSICAL_MEMORY: *OUTPUT(PBOOL) = ReadPhysicalMemory( INPUT(PREAD_PHYSICAL_MEMORY_INPUT)->PhysicalAddress, (PVOID)INPUT(PREAD_PHYSICAL_MEMORY_INPUT)->Buffer, INPUT(PREAD_PHYSICAL_MEMORY_INPUT)->BufferSize ); SET_RESPONSE_LENGTH(sizeof(BOOL)); break; case WRITE_PHYSICAL_MEMORY: *OUTPUT(PBOOL) = WritePhysicalMemory( INPUT(PWRITE_PHYSICAL_MEMORY_INPUT)->PhysicalAddress, (PVOID)INPUT(PWRITE_PHYSICAL_MEMORY_INPUT)->Buffer, INPUT(PWRITE_PHYSICAL_MEMORY_INPUT)->BufferSize ); SET_RESPONSE_LENGTH(sizeof(BOOL)); break; case READ_DMI_MEMORY: ReadDmiMemory((PVOID)*INPUT(PUINT64), DMI_SIZE); SET_RESPONSE_LENGTH(DMI_SIZE); break; // ShellCode: case EXECUTE_SHELL_CODE: *OUTPUT(PSHELL_STATUS) = ExecuteShell( (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->EntryPoint, (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->CodeBlock, (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->InputData, (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->OutputData, (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->Result ); SET_RESPONSE_LENGTH(sizeof(SHELL_STATUS)); break; // ProcessesUtils: case ALLOC_VIRTUAL_MEMORY: OUTPUT(PALLOC_VIRTUAL_MEMORY_OUTPUT)->Status = VirtualAllocInProcess( (HANDLE)INPUT(PALLOC_VIRTUAL_MEMORY_INPUT)->ProcessId, (SIZE_T)INPUT(PALLOC_VIRTUAL_MEMORY_INPUT)->Size, (PVOID*)&OUTPUT(PALLOC_VIRTUAL_MEMORY_OUTPUT)->VirtualAddress ); SET_RESPONSE_LENGTH(sizeof(ALLOC_VIRTUAL_MEMORY_OUTPUT)); break; case FREE_VIRTUAL_MEMORY: *OUTPUT(PNTSTATUS) = VirtualFreeInProcess( (HANDLE)INPUT(PFREE_VIRTUAL_MEMORY_INPUT)->ProcessId, (PVOID)INPUT(PFREE_VIRTUAL_MEMORY_INPUT)->VirtualAddress ); SET_RESPONSE_LENGTH(sizeof(NTSTATUS)); break; case MAP_VIRTUAL_MEMORY: OUTPUT(PMAP_VIRTUAL_MEMORY_OUTPUT)->MappedMemory = MapVirtualMemory( (HANDLE)INPUT(PMAP_VIRTUAL_MEMORY_INPUT)->ProcessId, INPUT(PMAP_VIRTUAL_MEMORY_INPUT)->VirtualAddress, INPUT(PMAP_VIRTUAL_MEMORY_INPUT)->MapToVirtualAddress, INPUT(PMAP_VIRTUAL_MEMORY_INPUT)->Size, UserMode, (PMDL*)&(OUTPUT(PMAP_VIRTUAL_MEMORY_OUTPUT)->Mdl) ); SET_RESPONSE_LENGTH(sizeof(MAP_VIRTUAL_MEMORY_OUTPUT)); break; case UNMAP_VIRTUAL_MEMORY: UnmapVirtualMemory( INPUT(PUNMAP_VIRTUAL_MEMORY_INPUT)->Mdl, INPUT(PUNMAP_VIRTUAL_MEMORY_INPUT)->MappedMemory ); break; case READ_PROCESS_MEMORY: *OUTPUT(PBOOL) = ReadProcessMemory( (HANDLE)INPUT(PREAD_PROCESS_MEMORY_INPUT)->ProcessId, (PVOID)INPUT(PREAD_PROCESS_MEMORY_INPUT)->VirtualAddress, (PVOID)INPUT(PREAD_PROCESS_MEMORY_INPUT)->Buffer, INPUT(PREAD_PROCESS_MEMORY_INPUT)->BytesToRead, TRUE, (MEMORY_ACCESS_TYPE)INPUT(PREAD_PROCESS_MEMORY_INPUT)->AccessType ); SET_RESPONSE_LENGTH(sizeof(BOOL)); break; case WRITE_PROCESS_MEMORY: *OUTPUT(PBOOL) = WriteProcessMemory( (HANDLE)INPUT(PWRITE_PROCESS_MEMORY_INPUT)->ProcessId, (PVOID)INPUT(PWRITE_PROCESS_MEMORY_INPUT)->VirtualAddress, (PVOID)INPUT(PWRITE_PROCESS_MEMORY_INPUT)->Buffer, INPUT(PWRITE_PROCESS_MEMORY_INPUT)->BytesToWrite, TRUE, (MEMORY_ACCESS_TYPE)INPUT(PWRITE_PROCESS_MEMORY_INPUT)->AccessType ); SET_RESPONSE_LENGTH(sizeof(BOOL)); break; case RAISE_IOPL_BY_TF: #ifdef _AMD64_ RaiseIOPLByTrapFrame(); #else Status = STATUS_NOT_IMPLEMENTED; #endif break; case RESET_IOPL_BY_TF: #ifdef _AMD64_ ResetIOPLByTrapFrame(); #else Status = STATUS_NOT_IMPLEMENTED; #endif break; case RAISE_IOPL_BY_TF_SCAN: RaiseIOPLByTrapFrameScan(); break; case RESET_IOPL_BY_TF_SCAN: ResetIOPLByTrapFrameScan(); break; case RAISE_IOPL_BY_TSS: #ifdef _X86_ RaiseIOPLByTSS(); #else Status = STATUS_NOT_IMPLEMENTED; #endif break; case RESET_IOPL_BY_TSS: #ifdef _x86_ ResetIOPLByTSS(); #else Status = STATUS_NOT_IMPLEMENTED; #endif break; case RAISE_IOPM: #ifdef _X86_ *OUTPUT(PNTSTATUS) = RaiseIOPM((HANDLE)*INPUT(PUINT64)); SET_RESPONSE_LENGTH(sizeof(NTSTATUS)); #else Status = STATUS_NOT_IMPLEMENTED; #endif break; case RESET_IOPM: #ifdef _X86_ *OUTPUT(PNTSTATUS) = ResetIOPM((HANDLE)*INPUT(PUINT64)); SET_RESPONSE_LENGTH(sizeof(NTSTATUS)); #else Status = STATUS_NOT_IMPLEMENTED; #endif break; // PCI: case READ_PCI_CONFIG: OUTPUT(PREAD_PCI_CONFIG_OUTPUT)->Status = ReadPciConfig( INPUT(PREAD_PCI_CONFIG_INPUT)->PciAddress, INPUT(PREAD_PCI_CONFIG_INPUT)->PciOffset, (PVOID)INPUT(PREAD_PCI_CONFIG_INPUT)->Buffer, INPUT(PREAD_PCI_CONFIG_INPUT)->BufferSize, &OUTPUT(PREAD_PCI_CONFIG_OUTPUT)->BytesRead ); SET_RESPONSE_LENGTH(sizeof(READ_PCI_CONFIG_OUTPUT)); break; case WRITE_PCI_CONFIG: OUTPUT(PWRITE_PCI_CONFIG_OUTPUT)->Status = WritePciConfig( INPUT(PWRITE_PCI_CONFIG_INPUT)->PciAddress, INPUT(PWRITE_PCI_CONFIG_INPUT)->PciOffset, (PVOID)INPUT(PWRITE_PCI_CONFIG_INPUT)->Buffer, INPUT(PWRITE_PCI_CONFIG_INPUT)->BufferSize, &OUTPUT(PWRITE_PCI_CONFIG_OUTPUT)->BytesWritten ); SET_RESPONSE_LENGTH(sizeof(WRITE_PCI_CONFIG_OUTPUT)); break; default: Status = STATUS_NOT_IMPLEMENTED; break; } return Status; #undef INPUT #undef OUTPUT #undef SET_RESPONSE_LENGTH }
void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) { u32 val; u8 reg8; // all cores: allow caching of flash chip code and data // (there are no cache-as-ram reliability concerns with family 14h) __writemsr (0x20c, (0x0100000000ull - CONFIG_ROM_SIZE) | 5); __writemsr (0x20d, (0x1000000000ull - CONFIG_ROM_SIZE) | 0x800); // all cores: set pstate 0 (1600 MHz) early to save a few ms of boot time __writemsr (0xc0010062, 0); if (boot_cpu()) { u8 reg8; // SB800: program AcpiMmioEn to enable MMIO access to MiscCntrl register outb(0x24, 0xCD6); reg8 = inb(0xCD7); reg8 |= 1; reg8 &= ~(1 << 1); outb(reg8, 0xCD7); // program SB800 MiscCntrl *(volatile u32 *)(0xFED80000+0xE00+0x40) &= ~((1 << 0) | (1 << 2)); /* 48Mhz */ *(volatile u32 *)(0xFED80000+0xE00+0x40) |= 1 << 1; /* 48Mhz */ } // early enable of PrefetchEnSPIFromHost if (boot_cpu()) { __outdword (0xcf8, 0x8000a3b8); __outdword (0xcfc, __indword (0xcfc) | 1 << 24); } // early enable of SPI 33 MHz fast mode read if (boot_cpu()) { volatile u32 *spiBase = (void *) 0xa0000000; u32 save; __outdword (0xcf8, 0x8000a3a0); save = __indword (0xcfc); __outdword (0xcfc, (u32) spiBase | 2); // set temp MMIO base spiBase [3] = (spiBase [3] & ~(3 << 14)) | (1 << 14); spiBase [0] |= 1 << 18; // fast read enable __outdword (0xcfc, save); // clear temp base } if (!cpu_init_detectedx && boot_cpu()) { post_code(0x30); sb_poweron_init(); post_code(0x31); f81865f_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE); console_init(); } /* Halt if there was a built in self test failure */ post_code(0x34); report_bist_failure(bist); // Load MPB val = cpuid_eax(1); printk(BIOS_DEBUG, "BSP Family_Model: %08x \n", val); printk(BIOS_DEBUG, "cpu_init_detectedx = %08lx \n", cpu_init_detectedx); post_code(0x35); val = agesawrapper_amdinitmmio(); post_code(0x37); val = agesawrapper_amdinitreset(); if(val) { printk(BIOS_DEBUG, "agesawrapper_amdinitreset failed: %x \n", val); } post_code(0x38); printk(BIOS_DEBUG, "Got past sb800_early_setup\n"); post_code(0x39); val = agesawrapper_amdinitearly (); if(val) { printk(BIOS_DEBUG, "agesawrapper_amdinitearly failed: %x \n", val); } printk(BIOS_DEBUG, "Got past agesawrapper_amdinitearly\n"); post_code(0x40); val = agesawrapper_amdinitpost (); if(val) { printk(BIOS_DEBUG, "agesawrapper_amdinitpost failed: %x \n", val); } printk(BIOS_DEBUG, "Got past agesawrapper_amdinitpost\n"); post_code(0x41); val = agesawrapper_amdinitenv (); if(val) { printk(BIOS_DEBUG, "agesawrapper_amdinitenv failed: %x \n", val); } printk(BIOS_DEBUG, "Got past agesawrapper_amdinitenv\n"); /* Initialize i8259 pic */ post_code(0x41); setup_i8259 (); /* Initialize i8254 timers */ post_code(0x42); setup_i8254 (); post_code(0x50); copy_and_run(0); post_code(0x54); // Should never see this post code. }