📄 tagged_loader.c
字号:
struct segheader{ unsigned char length; unsigned char vendortag; unsigned char reserved; unsigned char flags; unsigned long loadaddr; unsigned long imglength; unsigned long memlength;};struct imgheader{ unsigned long magic; unsigned long length; /* and flags */ union { struct { unsigned short bx, ds; } segoff; unsigned long location; } u; unsigned long execaddr;};/* Keep all context about loaded image in one place */static struct tagged_context{ struct imgheader img; /* copy of header */ unsigned long linlocation; /* addr of header */ unsigned long last0, last1; /* of prev segment */ unsigned long segaddr, seglen; /* of current segment */ unsigned char segflags; unsigned char first; unsigned long curaddr;} tctx;#define TAGGED_PROGRAM_RETURNS (tctx.img.length & 0x00000100) /* bit 8 */#define LINEAR_EXEC_ADDR (tctx.img.length & 0x80000000) /* bit 31 */static sector_t tagged_download(unsigned char *data, unsigned int len, int eof);static inline os_download_t tagged_probe(unsigned char *data, unsigned int len){ struct segheader *sh; unsigned long loc; if (*((uint32_t *)data) != 0x1B031336L) { return 0; } printf("(NBI)"); /* If we don't have enough data give up */ if (len < 512) return 0; /* Zero all context info */ memset(&tctx, 0, sizeof(tctx)); /* Copy first 4 longwords */ memcpy(&tctx.img, data, sizeof(tctx.img)); /* Memory location where we are supposed to save it */ tctx.segaddr = tctx.linlocation = ((tctx.img.u.segoff.ds) << 4) + tctx.img.u.segoff.bx; if (!prep_segment(tctx.segaddr, tctx.segaddr + 512, tctx.segaddr + 512, 0, 512)) { return 0; } /* Now verify the segments we are about to load */ loc = 512; for(sh = (struct segheader *)(data + ((tctx.img.length & 0x0F) << 2) + ((tctx.img.length & 0xF0) >> 2) ); (sh->length > 0) && ((unsigned char *)sh < data + 512); sh = (struct segheader *)((unsigned char *)sh + ((sh->length & 0x0f) << 2) + ((sh->length & 0xf0) >> 2)) ) { if (!prep_segment( sh->loadaddr, sh->loadaddr + sh->imglength, sh->loadaddr + sh->imglength, loc, loc + sh->imglength)) { return 0; } loc = loc + sh->imglength; if (sh->flags & 0x04) break; } if (!(sh->flags & 0x04)) return 0; /* Grab a copy */ memcpy(phys_to_virt(tctx.segaddr), data, 512); /* Advance to first segment descriptor */ tctx.segaddr += ((tctx.img.length & 0x0F) << 2) + ((tctx.img.length & 0xF0) >> 2); /* Remember to skip the first 512 data bytes */ tctx.first = 1; return tagged_download;}static sector_t tagged_download(unsigned char *data, unsigned int len, int eof){ int i; if (tctx.first) { tctx.first = 0; if (len > 512) { len -= 512; data += 512; /* and fall through to deal with rest of block */ } else return 0; } for (;;) { if (len == 0) /* Detect truncated files */ eof = 0; while (tctx.seglen == 0) { struct segheader sh; if (tctx.segflags & 0x04) { done(); if (LINEAR_EXEC_ADDR) { int result; /* no gateA20_unset for PM call */ result = xstart32(tctx.img.execaddr, virt_to_phys(&loaderinfo), tctx.linlocation, virt_to_phys(BOOTP_DATA_ADDR)); printf("Secondary program returned %d\n", result); if (!TAGGED_PROGRAM_RETURNS) { /* We shouldn't have returned */ result = -2; } if (result == 0) result = -2; longjmp(restart_etherboot, result); } else { gateA20_unset(); xstart16(tctx.img.execaddr, tctx.img.u.location, virt_to_phys(BOOTP_DATA_ADDR)); longjmp(restart_etherboot, -2); } } sh = *((struct segheader *)phys_to_virt(tctx.segaddr)); tctx.seglen = sh.imglength; if ((tctx.segflags = sh.flags & 0x03) == 0) tctx.curaddr = sh.loadaddr; else if (tctx.segflags == 0x01) tctx.curaddr = tctx.last1 + sh.loadaddr; else if (tctx.segflags == 0x02) tctx.curaddr = (Address)(meminfo.memsize * 1024L + 0x100000L) - sh.loadaddr; else tctx.curaddr = tctx.last0 - sh.loadaddr; tctx.last1 = (tctx.last0 = tctx.curaddr) + sh.memlength; tctx.segflags = sh.flags; tctx.segaddr += ((sh.length & 0x0F) << 2) + ((sh.length & 0xF0) >> 2); /* Avoid lock-up */ if ( sh.length == 0 ) longjmp(restart_etherboot, -2); } if ((len <= 0) && !eof) break; i = (tctx.seglen > len) ? len : tctx.seglen; memcpy(phys_to_virt(tctx.curaddr), data, i); tctx.seglen -= i; tctx.curaddr += i; len -= i; data += i; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -