📄 main.c
字号:
cpu->eax |= 3 << 8;
cpu->ecx &= ~0xffff;
cpu->ecx |= realdisksize >> 16;
cpu->edx &= ~0xffff;
cpu->edx |= realdisksize & 0xffff;
cpu->eflags &= ~1;
break;
// set media type for format
// ch: lower 8 bits of highest cylinder number
// cl: sectors per track (bits 0-5)
// high 2 bits of cylinder number (bit 6+7)
// dl: drive number
// returns:
// clear cf on success
// ah: status (1 = function not available)
// es:di: pointer to parameter table
case 0x18:
if ((cpu->edx & 0xff) != aoedrive) goto unhandled;
cpu->eax &= ~(0xff << 8);
cpu->eax |= 1 << 8;
cpu->eflags &= ~1;
break;
// extentions
// bx: 0x55aa
// dl: drive number
// returns:
// clear cf on success
// ah: version (1)
// bx: 0xaa55
// cx: support map (0b001)
case 0x41:
if ((cpu->edx & 0xff) != aoedrive) goto unhandled;
cpu->eax &= ~(0xff << 8);
cpu->eax |= 1 << 8;
cpu->ebx &= ~0xffff;
cpu->ebx |= 0xaa55;
cpu->ecx &= ~0xffff;
cpu->ecx |= 1;
cpu->eflags &= ~1;
break;
// extended read & extended write
// for write: al: write flags (bit 0: verify)
// dl: drive number
// ds:si: disk address packet
// (byte)0: size of packet (10h or 18h)
// (byte)1: reserved
// (word)2: count
// (long)4: buffer
// (longlong)8: lba
// returns:
// ah = 0 and clear cf on success
case 0x42:
case 0x43:
if ((cpu->edx & 0xff) != aoedrive) goto unhandled;
segmemcpy(((segment << 16) + (int)&rwpacket), ((cpu->ds << 16) + (cpu->esi & 0xffff)), sizeof(t_INT13_EXTENDED_READWRITE));
readwrite((((cpu->eax >> 8) & 0xff) == 0x42?1:0), rwpacket.lba, rwpacket.count, rwpacket.buffersegment, rwpacket.bufferoffset);
cpu->eax &= ~(0xff << 8);
cpu->eflags &= ~1;
break;
// extended get parameters
// dl: drive number
// ds:si: drive parameters packet to fill in
// (word)0: packet size (1ah)
// (word)2: information flags (3)
// (long)4: cylinders
// (long)8: heads
// (long)12: sectors
// (longlong)16: total size in sectors
// (word)24: bytes per sector
// returns:
// ah = 0 and clear cf on success
case 0x48:
if ((cpu->edx & 0xff) != aoedrive) goto unhandled;
memset(¶meterspacket, 0, sizeof(t_INT13_EXTENDED_GET_PARAMETERS));
parameterspacket.structsize = sizeof(t_INT13_EXTENDED_GET_PARAMETERS);
parameterspacket.flags = 3;
if (cylinders > 1024) {
parameterspacket.cylinders = 1024;
} else {
parameterspacket.cylinders = cylinders;
}
parameterspacket.heads = heads;
parameterspacket.sectors = sectors;
parameterspacket.disksize = realdisksize;
parameterspacket.sectorsize = SECTORSIZE;
segmemcpy(((cpu->ds << 16) | (cpu->esi & 0xffff)), ((segment << 16) + (int)¶meterspacket), sizeof(t_INT13_EXTENDED_GET_PARAMETERS));
cpu->eax &= ~(0xff << 8);
cpu->eflags &= ~1;
break;
default:
goto unhandled;
}
if (checksum != (c = chk())) {
printf("\n\nout checksum failed on tag: %d (%08x != %08x)\n", tag, checksum, c);
debug();
halt();
}
return;
unhandled:
#ifndef MINIMAL
printf("\n\nUnhandled INT13...\n");
printf("eax:%08x ebx:%08x ecx:%08x edx:%08x esi:%08x edi:%08x\n", cpu->eax, cpu->ebx, cpu->ecx, cpu->edx, cpu->esi, cpu->edi);
printf("ds:%04x es:%04x fs:%04x gs:%04x", cpu->ds, cpu->es, cpu->fs, cpu->gs);
printf(" ID:%d VIP:%d VIF:%d AC:%d VM:%d RF:%d NT:%d IOPL:%d%d\n", ((cpu->eflags >> 21) & 1), ((cpu->eflags >> 20) & 1), ((cpu->eflags >> 19) & 1), ((cpu->eflags >> 18) & 1), ((cpu->eflags >> 17) & 1), ((cpu->eflags >> 16) & 1), ((cpu->eflags >> 14) & 1), ((cpu->eflags >> 13) & 1), ((cpu->eflags >> 12) & 1));
printf("OF:%d DF:%d IF:%d TF:%d SF:%d ZF:%d AF:%d PF:%d CF:%d EFLAGS:%08x aoedrive:%02x\n", ((cpu->eflags >> 11) & 1), ((cpu->eflags >> 10) & 1), ((cpu->eflags >> 9) & 1), ((cpu->eflags >> 8) & 1), ((cpu->eflags >> 7) & 1), ((cpu->eflags >> 6) & 1), ((cpu->eflags >> 4) & 1), ((cpu->eflags >> 2) & 1), ((cpu->eflags >> 0) & 1), cpu->eflags, aoedrive);
#endif
// _CHAININTERRUPT(_oldint13, cpu);
printf("\n\nUnhandled INT13...\n");
halt();
}
void readwrite(unsigned char read, unsigned int lba, int count, unsigned short seg, unsigned short off) {
unsigned char sendbuffer[MAXPACKETSIZE];
unsigned char receivebuffer[MAXPACKETSIZE];
t_aoe* send = (t_aoe*)sendbuffer;
t_aoe* receive = (t_aoe*)receivebuffer;
unsigned int s = lba;
int i, n, c;
printf("tag:%d rw:%d seg:%04x off:%04x\n", tag, read, seg, off);
while (count > 0) {
if (count == 1) {
c = 1;
count = 0;
} else {
c = 2;
count -= 2;
}
memset(send, 0, sizeof(t_aoe));
memcpy(send->dst, servermac, 6);
memcpy(send->src, clientmac, 6);
send->protocol = htons(AOE_PROTOCOL);
send->ver = AOE_VERSION;
send->major = htons(major);
send->minor = minor;
send->tag = tag;
send->command = 0;
send->aflags = 0;
send->count = c;
if (read) {
send->cmd = 0x24; // READ SECTOR
} else {
send->cmd = 0x34; // WRITE SECTOR
}
send->lba0 = (s >> 0) & 255;
send->lba1 = (s >> 8) & 255;
send->lba2 = (s >> 16) & 255;
send->lba3 = (s >> 24) & 255;
// send->lba4 = (s >> 32) & 255;
// send->lba5 = (s >> 40) & 255;
send->lba4 = 0;
send->lba5 = 0;
if (read) {
n = 0;
} else {
segmemcpy(((segment << 16) + (int)send->data), ((seg << 16) + off), c * SECTORSIZE);
n = c;
}
sendreceive(send, sizeof(t_aoe) - (2 * SECTORSIZE), receive, &i);
if (read) {
segmemcpy(((seg << 16) + off), ((segment << 16) + (int)receive->data), c * SECTORSIZE);
}
s += c;
off += c * SECTORSIZE;
}
}
int pollisr() {
t_PXENV_UNDI_ISR isr;
memset((void *)&isr, 0, sizeof(isr));
isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
if (api(PXENV_UNDI_ISR, (void *)&isr)) apierror("PXENV_UNDI_ISR", isr.Status);
if (isr.FuncFlag == PXENV_UNDI_ISR_OUT_OURS) return 1;
return 0;
}
void sendreceive(t_aoe* sendbuffer, int sendsize, t_aoe* receivebuffer, int* receivesize) {
int old_21, old_a1;
int volatile oldisr;
int volatile oldint0;
int volatile oldint1;
int volatile oldint2;
int volatile oldint3;
int volatile oldint4;
int volatile oldint5;
int volatile oldint6;
int volatile oldint7;
int volatile oldint8;
cli();
timer = RECEIVETIMEOUT + 1;
sendbuffer->tag = tag;
gotisr = 0;
old_21 = inb(0x21);
old_a1 = inb(0xa1);
oldint0 = GETVECTOR(0x0);
oldint1 = GETVECTOR(0x1);
oldint2 = GETVECTOR(0x2);
oldint3 = GETVECTOR(0x3);
oldint4 = GETVECTOR(0x4);
oldint5 = GETVECTOR(0x5);
oldint6 = GETVECTOR(0x6);
oldint7 = GETVECTOR(0x7);
oldint8 = GETVECTOR(0x8);
SETVECTOR(0x0, (segment << 16) + (int)i0);
SETVECTOR(0x1, (segment << 16) + (int)i1);
SETVECTOR(0x2, (segment << 16) + (int)i2);
SETVECTOR(0x3, (segment << 16) + (int)i3);
SETVECTOR(0x4, (segment << 16) + (int)i4);
SETVECTOR(0x5, (segment << 16) + (int)i5);
SETVECTOR(0x6, (segment << 16) + (int)i6);
SETVECTOR(0x7, (segment << 16) + (int)i7);
SETVECTOR(0x8, (segment << 16) + (int)int8);
if (irq == 0) {
outb(~0, 0xa1);
outb(~1, 0x21);
} else {
if (irq <= 7) {
oldisr = GETVECTOR(irq + 0x8);
SETVECTOR(irq + 0x8, (segment << 16) + (int)isr);
// outb((inb(0x21) & (~(1 << irq))), 0x21);
outb(~0, 0xa1);
outb(~(1 << irq) & ~1, 0x21);
} else {
oldisr = GETVECTOR(irq + 0x70 - 0x8);
SETVECTOR(irq + 0x70 - 0x8, (segment << 16) + (int)isr);
// outb((inb(0xa1) & (~(1 << (irq - 8)))), 0xa1);
// outb((inb(0x21) & (~(1 << 2))), 0x21);
outb(~(1 << (irq - 8)), 0xa1);
outb(~(1 << 2) & ~1, 0x21);
}
}
while (1) {
//if (tag >= 732) printf("lets crash?\n");
if (timer > RECEIVETIMEOUT) {
sendpacket(sendbuffer, sendsize);
timer = 0;
}
//if (tag >= 732) printf("ok...\n");
gotisr = 0;
if (irq == 0) {
sti();
while (!(gotisr = pollisr()) && timer <= RECEIVETIMEOUT);
cli();
} else {
sti();
while (!gotisr && timer <= RECEIVETIMEOUT);
cli();
}
if (!gotisr) continue;
if (processpacket(receivebuffer, receivesize) <= 0) continue;
if (ntohs(receivebuffer->protocol) != AOE_PROTOCOL) continue;
if (ntohs(receivebuffer->major) != major) continue;
if (receivebuffer->minor != minor) continue;
if (!(receivebuffer->flags & (1 << 3))) continue;
if (receivebuffer->tag != tag) continue;
if (!(receivebuffer->status & (1 << 6))) continue; // Drive not ready
if (receivebuffer->status & (1 << 5)) {
printf("AoE ATA Drive error.\n");
halt();
}
break;
}
if (memcmp(servermac, "\xff\xff\xff\xff\xff\xff", 6) == 0) memcpy(servermac, receivebuffer->src, 6);
outb(old_a1, 0xa1);
outb(old_21, 0x21);
SETVECTOR(0x0, oldint0);
SETVECTOR(0x1, oldint1);
SETVECTOR(0x2, oldint2);
SETVECTOR(0x3, oldint3);
SETVECTOR(0x4, oldint4);
SETVECTOR(0x5, oldint5);
SETVECTOR(0x6, oldint6);
SETVECTOR(0x7, oldint7);
SETVECTOR(0x8, oldint8);
if (irq != 0) {
if (irq <= 7) {
SETVECTOR(irq + 0x8, oldisr);
// outb((inb(0x21) | (1 << irq)), 0x21);
} else {
SETVECTOR(irq + 0x70 - 0x8, oldisr);
// outb((inb(0xa1) | (1 << (irq - 8))), 0xa1);
}
}
tag++;
}
void sendpacket(void* packet, int size) {
t_PXENV_UNDI_TRANSMIT transmit;
t_PXENV_UNDI_TBD tbd;
memset((void *)&transmit, 0, sizeof(transmit));
memset((void *)&tbd, 0, sizeof(tbd));
transmit.Protocol = P_UNKNOWN;
transmit.XmitFlag = XMT_DESTADDR;
transmit.TBD.segment = segment;
transmit.TBD.offset = (unsigned int)&tbd;
tbd.ImmedLength = size;
tbd.Xmit.segment = segment;
tbd.Xmit.offset = (unsigned int)packet;
tbd.DataBlkCount = 0;
if (api(PXENV_UNDI_TRANSMIT, (void *)&transmit)) apierror("PXENV_UNDI_TRANSMIT", transmit.Status);
}
int processpacket(void* buffer, int* size) {
t_PXENV_UNDI_ISR isr;
int receiveddata = 0;
int r = 0;
memset((void *)&isr, 0, sizeof(isr));
isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
if (api(PXENV_UNDI_ISR, (void *)&isr)) apierror("PXENV_UNDI_ISR", isr.Status);
if (isr.FuncFlag == PXENV_UNDI_ISR_OUT_DONE || isr.FuncFlag == PXENV_UNDI_ISR_OUT_BUSY) return 0;
next:
if (isr.FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) goto release;
if (isr.FuncFlag == PXENV_UNDI_ISR_OUT_RECEIVE) {
if (isr.BufferLength > MAXPACKETSIZE) {
printf("Received packet too large... (%d)\n", isr.BufferLength);
goto release;
}
*size = isr.FrameLength;
segmemcpy(((segment << 16) + (int)buffer + receiveddata), ((isr.Frame.segment << 16) + isr.Frame.offset), isr.BufferLength);
receiveddata += isr.BufferLength;
r = 1;
goto release;
}
printf("Unknown function?...\n");
release:
memset((void *)&isr, 0, sizeof(isr));
isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
if (api(PXENV_UNDI_ISR, (void *)&isr)) apierror("PXENV_UNDI_ISR", isr.Status);
if (isr.FuncFlag != PXENV_UNDI_ISR_OUT_DONE && isr.FuncFlag != PXENV_UNDI_ISR_OUT_BUSY) goto next;
return r;
}
#ifndef MINIMAL
void printbuffer(unsigned short seg, unsigned short off, size_t n) {
int i, l, s;
unsigned char buffer[16];
l = 0;
while (n > 0) {
s = (n > 16?16:n);
segmemcpy((int)((segment << 16) + ((int)&buffer)), (((int)(seg << 16)) + off), s);
printf("%04x:%04x ", seg, off);
for (i = 0; i < s; i++) {
printf("%02x ", buffer[i]);
}
for (i = s; i < 16; i++) printf(" ");
for (i = 0; i < s; i++) {
if (buffer[i] > 32) {
putchar(buffer[i]);
} else {
putchar('.');
}
}
putchar('\n');
l++;
if ((l == 16) && (n > 16)) {
l = 0;
printf("Press a key\n");
getkey(0);
}
n -= s;
off += 16;
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -