Пример #1
0
// Enable PCI configuration space.
void EnableExtendedPCIConfigSpace(void)
{
    // Enable Access to the PCI Extended Configuration Space
    uint64 nbcfgData;
    ReadMSR(NB_CFG_MSR, &nbcfgData);
    nbcfgData |= ENABLE_CF8_EXT_CFG_MASK;
    WriteMSR(NB_CFG_MSR, nbcfgData);
}
Пример #2
0
/* Handles ioctl's from userspace.
   See ioctl codes in chipsec-common/chipsec_ioctl.h
 */
static kern_return_t pmem_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag,
                                struct proc *p) {
    //TODO (dynamically allocate these)
    pci_msg_t kpci;
    mmio_msg_t kmmio;
    cr_msg_t kcr;
    io_msg_t kio;
    msr_msg_t kmsr;
    cpuid_msg_t kcpuid;
    swsmi_msg_t kswsmi;
    hypercall_msg_t khypercall;
    msgbus_msg_t kmsgbus;
    cpudes_msg_t kcpudes;
    alloc_pmem_msg_t kalloc_pmem;

    pmem_log("cmd = %x", cmd);

    switch (cmd) {

        case CHIPSEC_IOC_RDPCI:
            pmem_log("RDPCI");
            log_addr((uint64_t) data, 64, "data");
            log_addr((uint64_t) &kpci, 64, "&krdpci");
            bcopy(data, &kpci, sizeof(pci_msg_t));
            pmem_log("ReadPCICfg(%lx, %lx, %lx, %lx, %lx)",
                     kpci.bus, kpci.device, kpci.function,
                     kpci.offset, kpci.length);

            kpci.value = ReadPCICfg(kpci.bus, kpci.device, kpci.function,
                             kpci.offset, kpci.length);
            pmem_log("kpci.value = %08x", kpci.value);

            bcopy(&kpci, data, sizeof(pci_msg_t));
            break;

        case CHIPSEC_IOC_WRPCI:
            pmem_log("WRPCI");
            bcopy(data, &kpci, sizeof(pci_msg_t));
            pmem_log("WritePCICfg(%lx, %lx, %lx, %lx, %lx, %lx)",
                     kpci.bus, kpci.device, kpci.function,
                     kpci.offset, kpci.length, kpci.value);

            WritePCICfg(kpci.bus, kpci.device, kpci.function,
                        kpci.offset, kpci.length, kpci.value);
            break;

        case CHIPSEC_IOC_RDMMIO:
            pmem_log("RDMMIO");
            bcopy(data, &kmmio, sizeof(mmio_msg_t));
            pmem_log("ReadMMIO(%lx, %x)", kmmio.addr, kmmio.length);
            kmmio.value = ReadMMIO(kmmio.addr, kmmio.length);
            pmem_log("val = %08llx", kmmio.value);

            bcopy(&kmmio, data, sizeof(mmio_msg_t));
            break;

        case CHIPSEC_IOC_WRMMIO:
            pmem_log("WRMMIO");
            bcopy(data, &kmmio, sizeof(mmio_msg_t));
            pmem_log("WriteMMIO(%lx, %x, %x)", kmmio.addr, kmmio.length,
                     (uint32_t) kmmio.value);

            WriteMMIO(kmmio.addr, kmmio.length, kmmio.value);
            break;

        case CHIPSEC_IOC_RDCR:
            pmem_log("RDCR");
            bcopy(data, &kcr, sizeof(cr_msg_t));
            pmem_log("ReadCR%d()", kcr.register_number);

            switch(kcr.register_number) {
                case 0:
                    kcr.value = ReadCR0();
                    break;
                case 2:
                    kcr.value = ReadCR2();
                    break;
                case 3:
                    kcr.value = ReadCR3();
                    break;
                case 4:
                    kcr.value = ReadCR4();
                    break;
                case 8:
                    kcr.value = ReadCR8();
                    break;
                default:
                    pmem_error("Incorrect CR number");
                    break;
            }
            bcopy(&kcr, data, sizeof(cr_msg_t));
            break;

        case CHIPSEC_IOC_WRCR:
            pmem_log("WRCR");
            bcopy(data, &kcr, sizeof(cr_msg_t));
            pmem_log("WriteCR%d(%x)", kcr.register_number, kcr.value);

            switch(kcr.register_number) {
                case 0:
                    WriteCR0(kcr.value);
                    break;
                case 2:
                    WriteCR2(kcr.value);
                    break;
                case 3:
                    WriteCR3(kcr.value);
                    break;
                case 4:
                    WriteCR4(kcr.value);
                    break;
                case 8:
                    WriteCR8(kcr.value);
                    break;
                default:
                    pmem_error("Incorrect CR number");
                    break;
            }
            bcopy(&kcr, data, sizeof(cr_msg_t));
            break;
            
        case CHIPSEC_IOC_RDIO:
            pmem_log("RDIO");
            bcopy(data,&kio, sizeof(io_msg_t));
            pmem_log("ReadIO %i from %x", kio.size, kio.port);
            kio.value = ReadIOPort((uint32_t)kio.port, kio.size);
            bcopy(&kio,data,sizeof(io_msg_t));
            break;
            
        case CHIPSEC_IOC_WRIO:
            pmem_log("WRIO");
            bcopy(data,&kio, sizeof(io_msg_t));
            pmem_log("WriteIO  %x to %x size %d", kio.value, kio.port,kio.size);
            WriteIOPort((uint32_t)kio.port, kio.size, (uint32_t)kio.value);
            break;
            
        case CHIPSEC_IOC_RDMSR:
            pmem_log("RDMSR");
            bcopy(data,&kmsr, sizeof(msr_msg_t));
            pmem_log("ReadMSR %x", kmsr.msr_num);
            ReadMSR(kmsr.msr_num, &kmsr.msr_lo, &kmsr.msr_hi);
            bcopy(&kmsr,data,sizeof(msr_msg_t));
            break;
            
        case CHIPSEC_IOC_WRMSR:
            pmem_log("WRMSR");
            bcopy(data,&kmsr, sizeof(msr_msg_t));
            pmem_log("WriteMSR  %x with %x%x", kmsr.msr_num, kmsr.msr_hi,kmsr.msr_lo);
            WriteMSR(kmsr.msr_num, kmsr.msr_lo, kmsr.msr_hi);
            break;
            
        case CHIPSEC_IOC_CPUID:
            pmem_log("CPUID");
            bcopy(data,&kcpuid, sizeof(cpuid_msg_t));
            pmem_log("WriteMSR  rax %x rcx %x", kcpuid.rax, kcpuid.rcx);
            chipCPUID(&kcpuid);
            bcopy(&kcpuid, data, sizeof(cpuid_msg_t));
            break;
        
        case CHIPSEC_IOC_SWSMI:
            pmem_log("SWSMI");
            bcopy(data,&kswsmi, sizeof(swsmi_msg_t));
            pmem_log("Blah");
            SWSMI(&kswsmi);
            bcopy(&kswsmi, data, sizeof(swsmi_msg_t));
            break;
            
        case CHIPSEC_IOC_HYPERCALL:
            pmem_log("HYPERCALL");
            bcopy(data,&khypercall, sizeof(hypercall_msg_t));
            pmem_log("Hypercall Data");
            khypercall.hypercall_page = (uint64_t) & hypercall_page;
            hypercall(khypercall.rdi, khypercall.rsi, khypercall.rdx, khypercall.rcx, khypercall.r8, khypercall.r9, khypercall.rax, khypercall.rbx, khypercall.r10, khypercall.r11, khypercall.xmm_buffer, khypercall.hypercall_page);
            bcopy(&khypercall,data, sizeof(hypercall_msg_t));
            break;
            
        case CHIPSEC_IOC_MSGBUS_SEND_MESSAGE:
            pmem_log("MSGBUG SEND MESSAGE");
            bcopy(data,&kmsgbus, sizeof(msgbus_msg_t));
            pmem_log("MSGBUS DATA:");
            if (kmsgbus.direction & MSGBUS_MDR_IN_MASK){
                //Write data to MDR register
                WritePCICfg(MSGBUS_BUS, MSGBUS_DEV, MSGBUS_FUN, MDR, 4, (uint32_t)kmsgbus.mdr);
            }
            //TODO investigate comment (from linux driver)
            //Write extended address to MCRX register if address is > 0xff
            if (kmsgbus.mcrx != 0){
                WritePCICfg(MSGBUS_BUS, MSGBUS_DEV, MSGBUS_FUN, MCRX, 4, (uint32_t)kmsgbus.mcrx);
            }
            //Write to MCR register to send the message on the message bus
            WritePCICfg(MSGBUS_BUS, MSGBUS_DEV, MSGBUS_FUN, MCR, 4, (uint32_t)kmsgbus.mcr);
            
            if (kmsgbus.direction & MSGBUS_MDR_OUT_MASK){
                //Read data from MDR register
                kmsgbus.mdr_out = ReadPCICfg(MSGBUS_BUS, MSGBUS_DEV, MSGBUS_FUN, MDR, 4);
            }
            bcopy(&kmsgbus, data, sizeof(msgbus_msg_t));
            break;
        
        case CHIPSEC_IOC_CPU_DESCRIPTOR_TABLE:
            descriptor_table_record kdtr;
            IOMemoryDescriptor* io_desc;
            IOMemoryMap* io_map;
            pmem_log("GET CPU DESCRIPTOR TABLE");
            bcopy(data, &kcpudes, sizeof(cpudes_msg_t));
            pmem_log("GET_CPU_DESCRIPTOR TABLE %x thread %d", kcpudes.des_table_code, kcpudes.cpu_thread_id);
            switch (kcpudes.des_table_code)
            {
                case CPU_DT_CODE_GDTR:
                    store_gdtr(&kdtr);
                    break;
                
                case CPU_DT_CODE_LDTR:
                    store_ldtr(&kdtr);
                    break;
                
                case CPU_DT_CODE_IDTR:
                    store_idtr(&kdtr);
                    break;
            
            }
            xlate_pa_va(kdtr.base, &io_desc, &io_map);
            kcpudes.limit = kdtr.limit;
            kcpudes.base_hi = (kdtr.base >> 32);
            kcpudes.base_lo = (kdtr.base & 0xFFFFFFFF);
            kcpudes.pa_hi = (io_map->getPhysicalAddress() >> 32);
            kcpudes.pa_lo = (io_map->getPhysicalAddress() & 0xFFFFFFFF);
            bcopy(&kcpudes, data, sizeof(cpudes_msg_t));
            break;
            
        case CHIPSEC_IOC_ALLOC_PHYSMEM:
            void *va;
            IOMemoryDescriptor* io_desc1;
            IOMemoryMap* io_map1;
            pmem_log("ALLOC PHYSMEM");
            bcopy(data, &kalloc_pmem, sizeof(alloc_pmem_msg_t));
            pmem_log("Allocating %x memory, with pa limit of %x", kalloc_pmem.num_bytes, kalloc_pmem.max_addr);
            va = IOMalloc((uint32_t)kalloc_pmem.num_bytes);
            if (!va){
                pmem_log("Could not allocate memory");
                return -EFAULT;
            }
            memset(va, 0, kalloc_pmem.num_bytes);
            
            if ( xlate_pa_va((addr64_t) va, &io_desc1, &io_map1) ){
                pmem_log("Could not map memory");
            }
            if (io_map1->getPhysicalAddress() > kalloc_pmem.max_addr){
                pmem_log("Allocate memory is above max_pa");
            }
            kalloc_pmem.virt_addr = (uint64_t)va;
            kalloc_pmem.phys_addr = io_map1->getPhysicalAddress();
            bcopy(&kalloc_pmem, data, sizeof(alloc_pmem_msg_t));
            break;

        default:
            pmem_error("Illegal ioctl %08lx", cmd);
            return -EFAULT;
    }
    return KERN_SUCCESS;
}