uint32_t smm_deactivate(void) { uint32_t adr; uint32_t ret = SMM_DEFAULT; uint32_t smi_en; unsigned if_backup; if_backup = cli(); if (pmbase != 0) { adr = pmbase+0x30; /* SMI_EN I/O register is at pmbase+0x30 */ /* read current value to return it on end */ ret = inportl(adr); /* set to 0 (only writable bits will be changed...) */ smi_en = 0; //&= ~1; outportl(adr, smi_en); /* read again to see what has changed */ smi_en = inportl(adr); IFVV printf("SMI_EN: 0x%x (after setting SMI_EN to 0; bit 0 is GBL_SMI_EN)\n", smi_en); /* if GBL_SMI_EN (bit #0) is 0, deactivation was successful */ if ((smi_en & 0x01) == 0) { IFV printf("SMI globally disabled\n"); } else { printf("Warning: SMI was not disabled!\n"); } } if (if_backup) sti(); return ret; }
void smm_init(void) { uint32_t adr; uint32_t smi_en; unsigned if_backup; if_backup = cli(); /* adr = (1<<31) | (LPC_BUS << 16) | (LPC_DEVICE << 11) | (LPC_FUNC << 8) | LPC_OFFSET; outportl(CONFIG_ADDRESS, adr); pmbase = inportl(CONFIG_DATA); */ pmbase = pci_config_read(LPC_BUS, LPC_DEVICE, LPC_FUNC, LPC_OFFSET); pmbase &= 0xFF80; IFV printf("SMM: located pmbase : 0x%x \n", pmbase); if (pmbase != 0) { adr = pmbase+0x30; /* SMI_EN I/O register is at pmbase+0x30 */ /* read SMI_EN and display */ smi_en = inportl(adr); bak_smi_en = smi_en; IFVV printf("SMI_EN: 0x%x \n", smi_en); } if (if_backup) sti(); }
uint32_t pci_read_dword(uint8_t bus, uint8_t slot, uint8_t func, uint32_t offset) { uint32_t id = ((bus) << 16) | ((slot) << 11) | ((func) << 8); uint32_t addr = 0x80000000 | id | (offset & 0xfc); outportl(0xCF8, addr); return inportl(0xCFC); }
static int rtl_irq_handler(struct regs *r) { uint16_t status = inports(rtl_iobase + RTL_PORT_ISR); if (!status) { return 0; } outports(rtl_iobase + RTL_PORT_ISR, status); irq_ack(rtl_irq); if (status & 0x01 || status & 0x02) { /* Receive */ while((inportb(rtl_iobase + RTL_PORT_CMD) & 0x01) == 0) { int offset = cur_rx % 0x2000; #if 0 uint16_t buf_addr = inports(rtl_iobase + RTL_PORT_RXADDR); uint16_t buf_ptr = inports(rtl_iobase + RTL_PORT_RXPTR); uint8_t cmd = inportb(rtl_iobase + RTL_PORT_CMD); #endif uint32_t * buf_start = (uint32_t *)((uintptr_t)rtl_rx_buffer + offset); uint32_t rx_status = buf_start[0]; int rx_size = rx_status >> 16; if (rx_status & (0x0020 | 0x0010 | 0x0004 | 0x0002)) { debug_print(WARNING, "rx error :("); } else { uint8_t * buf_8 = (uint8_t *)&(buf_start[1]); last_packet = malloc(rx_size); uintptr_t packet_end = (uintptr_t)buf_8 + rx_size; if (packet_end > (uintptr_t)rtl_rx_buffer + 0x2000) { size_t s = ((uintptr_t)rtl_rx_buffer + 0x2000) - (uintptr_t)buf_8; memcpy(last_packet, buf_8, s); memcpy((void *)((uintptr_t)last_packet + s), rtl_rx_buffer, rx_size - s); } else { memcpy(last_packet, buf_8, rx_size); } rtl_enqueue(last_packet); } cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; outports(rtl_iobase + RTL_PORT_RXPTR, cur_rx - 16); } wakeup_queue(rx_wait); } if (status & 0x08 || status & 0x04) { unsigned int i = inportl(rtl_iobase + RTL_PORT_TXSTAT + 4 * dirty_tx); (void)i; dirty_tx++; if (dirty_tx == 5) dirty_tx = 0; } return 1; }
uint32 pci_read_conf32(uint8 bus, uint8 dev, uint8 func, uint8 reg) { uint32 ret; uint32 port = (0x80000000U)|(bus<<16)|(dev<<11)|(func<<8)|(reg); outportl(0xcf8, port); ret = inportl(0xcfc); return ret; }
static unsigned long pci_dev_read_dw(pci_dev *pdev, unsigned int index) { unsigned long tmp; unsigned long pci_config_addr32 = 0x80000000L | (((unsigned long)pdev->bus) << 16) | (((unsigned long)pdev->dev) << 11) | (((unsigned long)pdev->func) << 8) | index; outportl(0x0cf8, pci_config_addr32); tmp = inportl(0x0cfc); return tmp; }
uint32_t pci_read_field(uint32_t device, int field, int size) { outportl(PCI_ADDRESS_PORT, pci_get_addr(device, field)); if (size == 4) { uint32_t t = inportl(PCI_VALUE_PORT); return t; } else if (size == 2) { uint16_t t = inports(PCI_VALUE_PORT + (field & 2)); return t; } else if (size == 1) { uint8_t t = inportb(PCI_VALUE_PORT + (field & 3)); return t; } return 0xFFFF; }
uint32_t smm_restore(uint32_t value) { unsigned if_backup; uint32_t ret = SMM_DEFAULT; if_backup = cli(); if (pmbase != 0) { /* read current value to return it on end */ ret = inportl(pmbase+0x30); /* restore */ outportl(pmbase+0x30, (value==SMM_DEFAULT)?bak_smi_en:value); } if (if_backup) sti(); return ret; }
uint32 readBCR(uint32 base, uint32 index) { outportl(base + RAP, index); return inportl(base + BDP); }
uint32_t pci_read32(uint32_t id, uint32_t reg) { uint32_t addr = 0x80000000 | id | (reg & 0xfc); outportl(PCI_CONFIG_ADDR, addr); return inportl(PCI_CONFIG_DATA); }
static uint32_t rddm32(CMI8738_Driver_t* ds, uint32_t offset) { return inportl(ds->base_addr + offset); }
int vm86_emulate(struct vm86_context *vm86ctx) { int eaten = 1; int data32 = 0, addr32 = 0, rep = 0, segp = 0; int done = 0; uint16_t ip = LOWORD(vm86ctx->eip), sp = LOWORD(vm86ctx->esp); do { switch(*(uint8_t *)LADDR(vm86ctx->cs, ip)) { case 0x66: /*32-bit data*/ data32=1; break; case 0x67: /*32-bit addr*/ addr32=1; break; case 0xf2: /*REPNZ/REPNE*/ rep=1; break; case 0xf3: /*REP/REPZ/REPE*/ rep=1; break; case 0x2e: /*CS*/ segp=56; break; case 0x3e: /*DS*/ segp=76; break; case 0x26: /*ES*/ segp=72; break; case 0x36: /*SS*/ segp=68; break; case 0x65: /*GS*/ segp=84; break; case 0x64: /*FS*/ segp=80; break; case 0xf0: /*LOCK*/ break; default: done = 1; break; } if(done) break; ip++; } while(1); switch(*(uint8_t *)LADDR(vm86ctx->cs, ip)) { case 0xfa: /*CLI*/ vm86ctx->eflags &= ~EFLAGS_IF; ip++; break; case 0xfb: /*STI*/ vm86ctx->eflags |= EFLAGS_IF; ip++; break; case 0x9c: /*PUSHF*/ if(data32) { sp -= 4; *(uint32_t *)LADDR(vm86ctx->ss, sp) = vm86ctx->eflags & 0x001cffff; } else { sp -= 2; *(uint16_t *)LADDR(vm86ctx->ss, sp) = (uint16_t)vm86ctx->eflags; } ip++; break; case 0x9d: /*POPF*/ if(data32) { uint32_t eflags = *(uint32_t *)LADDR(vm86ctx->ss, sp); vm86ctx->eflags &= 0x1b3000/*VM, RF, IOPL, VIP, VIF*/; eflags &= ~0x1b3000; vm86ctx->eflags |= eflags; sp += 4; } else { uint32_t eflags = *(uint16_t *)LADDR(vm86ctx->ss, sp); vm86ctx->eflags &= 0xffff3000/*IOPL*/; eflags &= ~0xffff3000; vm86ctx->eflags |= eflags; sp += 2; } ip++; break; case 0xcd: /*INT*/ sp -= 2; *(uint16_t *)LADDR(vm86ctx->ss, sp) = (uint16_t)vm86ctx->eflags; sp -= 2; *(uint16_t *)LADDR(vm86ctx->ss, sp) = vm86ctx->cs; sp -= 2; *(uint16_t *)LADDR(vm86ctx->ss, sp) = ip + 2; { uint16_t *ivt = (uint16_t *)0; uint8_t x = *(uint8_t *)LADDR(vm86ctx->cs, ip + 1); ip = ivt[x * 2 + 0]; vm86ctx->cs = ivt[x * 2 + 1]; } break; case 0xcf: /*IRET*/ if(data32) { ip = *(uint32_t *)LADDR(vm86ctx->ss, sp); sp += 4; vm86ctx->cs = *(uint32_t *)LADDR(vm86ctx->ss, sp); sp += 4; uint32_t eflags = *(uint32_t *)LADDR(vm86ctx->ss, sp); vm86ctx->eflags &= 0x1a3000/*VM, IOPL, VIP, VIF*/; eflags &= ~0x1a3000; vm86ctx->eflags |= eflags; sp += 4; } else { ip = *(uint16_t *)LADDR(vm86ctx->ss, sp); sp += 2; vm86ctx->cs = *(uint16_t *)LADDR(vm86ctx->ss, sp); sp += 2; uint32_t eflags = *(uint16_t *)LADDR(vm86ctx->ss, sp); vm86ctx->eflags &= 0xffff3000/*IOPL*/; eflags &= ~0xffff3000; vm86ctx->eflags |= eflags; sp += 2; } break; case 0xe6:/*OUT imm8, AL*/ outportb(*(uint8_t *)LADDR(vm86ctx->cs, ip + 1), LOBYTE(LOWORD(vm86ctx->eax))); ip += 2; break; case 0xe7:/*OUT imm8, (E)AX*/ if(data32) { outportl(*(uint8_t *)LADDR(vm86ctx->cs, ip + 1), vm86ctx->eax); } else { outportw(*(uint8_t *)LADDR(vm86ctx->cs, ip + 1), LOWORD(vm86ctx->eax)); } ip += 2; break; case 0xee:/*OUT DX, AL*/ outportb(LOWORD(vm86ctx->edx), LOBYTE(LOWORD(vm86ctx->eax))); ip++; break; case 0xef:/*OUT DX, (E)AX*/ if(data32) { outportl(LOWORD(vm86ctx->edx), vm86ctx->eax); } else { outportw(LOWORD(vm86ctx->edx), LOWORD(vm86ctx->eax)); } ip++; break; case 0xe4:/*IN AL, imm8*/ { uint8_t al = inportb(*(uint8_t *)LADDR(vm86ctx->cs, ip + 1)); vm86ctx->eax = (vm86ctx->eax & 0xffffff00) | al; } ip += 2; break; case 0xe5:/*IN (E)AX, imm8*/ if(data32) { vm86ctx->eax = inportl(*(uint8_t *)LADDR(vm86ctx->cs, ip + 1)); } else { uint16_t ax = inportw(*(uint8_t *)LADDR(vm86ctx->cs, ip + 1)); vm86ctx->eax = (vm86ctx->eax & 0xffff0000) | ax; } ip += 2; break; case 0xec:/*IN AL, DX*/ { uint8_t al = inportb(LOWORD(vm86ctx->edx)); vm86ctx->eax = (vm86ctx->eax & 0xffffff00) | al; } ip += 1; break; case 0xed:/*IN (E)AX, DX*/ if(data32) { vm86ctx->eax = inportl(LOWORD(vm86ctx->edx)); } else { uint16_t ax = inportw(LOWORD(vm86ctx->edx)); vm86ctx->eax = (vm86ctx->eax & 0xffff0000) | ax; } ip++; break; case 0x6c:/*INSB; INS m8, DX*/ { if(addr32) { uint32_t ecx = rep ? vm86ctx->ecx : 1; while(ecx) { *(uint8_t *)LADDR(vm86ctx->es, vm86ctx->edi/*XXX*/) = inportb(LOWORD(vm86ctx->edx)); ecx--; vm86ctx->edi += (vm86ctx->eflags & 0x400)?-1:1; } if(rep) vm86ctx->ecx = ecx; } else { uint16_t cx=rep ? LOWORD(vm86ctx->ecx) : 1, di=LOWORD(vm86ctx->edi); while(cx) { *(uint8_t *)LADDR(vm86ctx->es, di) = inportb(LOWORD(vm86ctx->edx)); cx--; di += (vm86ctx->eflags & 0x400)?-1:1; } if(rep) vm86ctx->ecx = (vm86ctx->ecx & 0xffff0000) | cx; vm86ctx->edi = (vm86ctx->edi & 0xffff0000) | di; } } ip++; break; case 0x6d:/*INSW; INSD; INS m16/m32, DX*/ { if(addr32) { uint32_t ecx = rep ? vm86ctx->ecx : 1; while(ecx) { if(data32) { *(uint32_t *)LADDR(vm86ctx->es, vm86ctx->edi/*XXX*/) = inportl(LOWORD(vm86ctx->edx)); vm86ctx->edi += (vm86ctx->eflags & 0x400)?-4:4; } else { *(uint16_t *)LADDR(vm86ctx->es, vm86ctx->edi/*XXX*/) = inportw(LOWORD(vm86ctx->edx)); vm86ctx->edi += (vm86ctx->eflags & 0x400)?-2:2; } ecx--; } if(rep) vm86ctx->ecx = ecx; } else { uint16_t cx=rep ? LOWORD(vm86ctx->ecx) : 1, di=LOWORD(vm86ctx->edi); while(cx) { if(data32) { *(uint32_t *)LADDR(vm86ctx->es, di) = inportl(LOWORD(vm86ctx->edx)); di += (vm86ctx->eflags & 0x400)?-4:4; } else { *(uint16_t *)LADDR(vm86ctx->es, di) = inportw(LOWORD(vm86ctx->edx)); di += (vm86ctx->eflags & 0x400)?-2:2; } cx--; } if(rep) vm86ctx->ecx = (vm86ctx->ecx & 0xffff0000) | cx; vm86ctx->edi = (vm86ctx->edi & 0xffff0000) | di; } } ip++; break; case 0x6e:/*OUTSB; OUTS DX, m8*/ { uint16_t seg = vm86ctx->ds; if(segp) seg = *(uint16_t *)(((uint8_t *)vm86ctx)+segp); if(addr32) { uint32_t ecx = rep ? vm86ctx->ecx : 1; while(ecx) { outportb(LOWORD(vm86ctx->edx), *(uint8_t *)LADDR(seg, vm86ctx->esi/*XXX*/)); ecx--; vm86ctx->esi += (vm86ctx->eflags & 0x400)?-1:1; } if(rep) vm86ctx->ecx = ecx; } else { uint16_t cx=rep ? LOWORD(vm86ctx->ecx) : 1, si=LOWORD(vm86ctx->esi); while(cx) { outportb(LOWORD(vm86ctx->edx), *(uint8_t *)LADDR(seg, si)); cx--; si += (vm86ctx->eflags & 0x400)?-1:1; } if(rep) vm86ctx->ecx = (vm86ctx->ecx & 0xffff0000) | cx; vm86ctx->esi = (vm86ctx->esi & 0xffff0000) | si; } } ip++; break; case 0x6f:/*OUTSW; OUTSD; OUTS DX, m16/32*/ { uint16_t seg = vm86ctx->ds; if(segp) seg = *(uint16_t *)(((uint8_t *)vm86ctx)+segp); if(addr32) { uint32_t ecx = rep ? vm86ctx->ecx : 1; while(ecx) { if(data32) { outportl(LOWORD(vm86ctx->edx), *(uint32_t *)LADDR(seg, vm86ctx->esi/*XXX*/)); vm86ctx->esi += (vm86ctx->eflags & 0x400)?-4:4; } else { outportw(LOWORD(vm86ctx->edx), *(uint16_t *)LADDR(seg, vm86ctx->esi/*XXX*/)); vm86ctx->esi += (vm86ctx->eflags & 0x400)?-2:2; } ecx--; } if(rep) vm86ctx->ecx = ecx; } else { uint16_t cx=rep ? LOWORD(vm86ctx->ecx) : 1, si=LOWORD(vm86ctx->esi); while(cx) { if(data32) { outportl(LOWORD(vm86ctx->edx), *(uint32_t *)LADDR(seg, si)); si += (vm86ctx->eflags & 0x400)?-4:4; } else { outportw(LOWORD(vm86ctx->edx), *(uint16_t *)LADDR(seg, si)); si += (vm86ctx->eflags & 0x400)?-2:2; } cx--; } if(rep) vm86ctx->ecx = (vm86ctx->ecx & 0xffff0000) | cx; vm86ctx->esi = (vm86ctx->esi & 0xffff0000) | si; } } ip++; break; default: eaten = 0; break; } vm86ctx->eip = (vm86ctx->eip & 0xffff0000) | ip; vm86ctx->esp = (vm86ctx->esp & 0xffff0000) | sp; return eaten; }