1bd389b36SDavid du Colombier #include <u.h> 2bd389b36SDavid du Colombier #include <libc.h> 3bd389b36SDavid du Colombier #include <bio.h> 4bd389b36SDavid du Colombier #include <bootexec.h> 5bd389b36SDavid du Colombier #include <mach.h> 63e12c5d1SDavid du Colombier 73e12c5d1SDavid du Colombier /* 83e12c5d1SDavid du Colombier * All a.out header types. The dummy entry allows canonical 93e12c5d1SDavid du Colombier * processing of the union as a sequence of longs 103e12c5d1SDavid du Colombier */ 113e12c5d1SDavid du Colombier 123e12c5d1SDavid du Colombier typedef struct { 133e12c5d1SDavid du Colombier union{ 143e12c5d1SDavid du Colombier Exec; /* in a.out.h */ 153e12c5d1SDavid du Colombier struct mipsexec; /* Hobbit uses this header too */ 16*219b2ee8SDavid du Colombier struct mips4kexec; 173e12c5d1SDavid du Colombier struct sparcexec; 183e12c5d1SDavid du Colombier struct nextexec; 193e12c5d1SDavid du Colombier struct i960exec; 203e12c5d1SDavid du Colombier } e; 213e12c5d1SDavid du Colombier long dummy; /* padding to ensure extra long */ 223e12c5d1SDavid du Colombier } ExecHdr; 233e12c5d1SDavid du Colombier 243e12c5d1SDavid du Colombier static void i960boot(Fhdr *, ExecHdr *); 253e12c5d1SDavid du Colombier static void nextboot(Fhdr *, ExecHdr *); 263e12c5d1SDavid du Colombier static void sparcboot(Fhdr *, ExecHdr *); 273e12c5d1SDavid du Colombier static void mipsboot(Fhdr *, ExecHdr *); 28*219b2ee8SDavid du Colombier static void mips4kboot(Fhdr *, ExecHdr *); 293e12c5d1SDavid du Colombier static void common(Fhdr *, ExecHdr *); 303e12c5d1SDavid du Colombier static void adotout(Fhdr *, ExecHdr *); 313e12c5d1SDavid du Colombier static void setsym(Fhdr *, long, long, long, long); 323e12c5d1SDavid du Colombier static void setdata(Fhdr *, long, long, long, long); 333e12c5d1SDavid du Colombier static void settext(Fhdr *, long, long, long, long); 343e12c5d1SDavid du Colombier static void hswal(long *, int, long (*) (long)); 35*219b2ee8SDavid du Colombier static long _round(long, long); 363e12c5d1SDavid du Colombier 373e12c5d1SDavid du Colombier /* 383e12c5d1SDavid du Colombier * definition of per-executable file type structures 393e12c5d1SDavid du Colombier */ 403e12c5d1SDavid du Colombier 413e12c5d1SDavid du Colombier typedef struct Exectable{ 423e12c5d1SDavid du Colombier long magic; /* big-endian magic number of file */ 433e12c5d1SDavid du Colombier char *name; /* executable identifier */ 443e12c5d1SDavid du Colombier int type; /* Internal code */ 453e12c5d1SDavid du Colombier Mach *mach; /* Per-machine data */ 463e12c5d1SDavid du Colombier ulong hsize; /* header size */ 473e12c5d1SDavid du Colombier long (*swal)(long); /* beswal or leswal */ 483e12c5d1SDavid du Colombier void (*hparse)(Fhdr *, ExecHdr *); 493e12c5d1SDavid du Colombier } ExecTable; 503e12c5d1SDavid du Colombier 513e12c5d1SDavid du Colombier extern Mach mmips; 523e12c5d1SDavid du Colombier extern Mach msparc; 533e12c5d1SDavid du Colombier extern Mach m68020; 543e12c5d1SDavid du Colombier extern Mach mi386; 553e12c5d1SDavid du Colombier extern Mach mi960; 56*219b2ee8SDavid du Colombier extern Mach m3210; 573e12c5d1SDavid du Colombier 583e12c5d1SDavid du Colombier ExecTable exectab[] = 593e12c5d1SDavid du Colombier { 603e12c5d1SDavid du Colombier { V_MAGIC, /* Mips v.out */ 613e12c5d1SDavid du Colombier "mips plan 9 executable", 623e12c5d1SDavid du Colombier FMIPS, 633e12c5d1SDavid du Colombier &mmips, 643e12c5d1SDavid du Colombier sizeof(Exec), 653e12c5d1SDavid du Colombier beswal, 663e12c5d1SDavid du Colombier adotout }, 673e12c5d1SDavid du Colombier { 0x160<<16, /* Mips boot image */ 683e12c5d1SDavid du Colombier "mips plan 9 boot image", 693e12c5d1SDavid du Colombier FMIPSB, 703e12c5d1SDavid du Colombier &mmips, 713e12c5d1SDavid du Colombier sizeof(struct mipsexec), 723e12c5d1SDavid du Colombier beswal, 733e12c5d1SDavid du Colombier mipsboot }, 74*219b2ee8SDavid du Colombier { (0x160<<16)|3, /* Mips boot image */ 75*219b2ee8SDavid du Colombier "mips 4k plan 9 boot image", 76*219b2ee8SDavid du Colombier FMIPSB, 77*219b2ee8SDavid du Colombier &mmips, 78*219b2ee8SDavid du Colombier sizeof(struct mips4kexec), 793e12c5d1SDavid du Colombier beswal, 80*219b2ee8SDavid du Colombier mips4kboot }, 813e12c5d1SDavid du Colombier { K_MAGIC, /* Sparc k.out */ 823e12c5d1SDavid du Colombier "sparc plan 9 executable", 833e12c5d1SDavid du Colombier FSPARC, 843e12c5d1SDavid du Colombier &msparc, 853e12c5d1SDavid du Colombier sizeof(Exec), 863e12c5d1SDavid du Colombier beswal, 873e12c5d1SDavid du Colombier adotout }, 883e12c5d1SDavid du Colombier { 0x01030107, /* Sparc boot image */ 893e12c5d1SDavid du Colombier "sparc plan 9 boot image", 903e12c5d1SDavid du Colombier FSPARCB, 913e12c5d1SDavid du Colombier &msparc, 923e12c5d1SDavid du Colombier sizeof(struct sparcexec), 933e12c5d1SDavid du Colombier beswal, 943e12c5d1SDavid du Colombier sparcboot }, 953e12c5d1SDavid du Colombier { A_MAGIC, /* 68020 2.out & boot image */ 963e12c5d1SDavid du Colombier "68020 plan 9 executable", 973e12c5d1SDavid du Colombier F68020, 983e12c5d1SDavid du Colombier &m68020, 993e12c5d1SDavid du Colombier sizeof(Exec), 1003e12c5d1SDavid du Colombier beswal, 1013e12c5d1SDavid du Colombier common }, 1023e12c5d1SDavid du Colombier { 0xFEEDFACE, /* Next boot image */ 1033e12c5d1SDavid du Colombier "next plan 9 boot image", 1043e12c5d1SDavid du Colombier FNEXTB, 1053e12c5d1SDavid du Colombier &m68020, 1063e12c5d1SDavid du Colombier sizeof(struct nextexec), 1073e12c5d1SDavid du Colombier beswal, 1083e12c5d1SDavid du Colombier nextboot }, 1093e12c5d1SDavid du Colombier { I_MAGIC, /* I386 8.out & boot image */ 1103e12c5d1SDavid du Colombier "386 plan 9 executable", 1113e12c5d1SDavid du Colombier FI386, 1123e12c5d1SDavid du Colombier &mi386, 1133e12c5d1SDavid du Colombier sizeof(Exec), 1143e12c5d1SDavid du Colombier beswal, 1153e12c5d1SDavid du Colombier common }, 1163e12c5d1SDavid du Colombier { J_MAGIC, /* I960 6.out (big-endian) */ 1173e12c5d1SDavid du Colombier "960 plan 9 executable", 1183e12c5d1SDavid du Colombier FI960, 1193e12c5d1SDavid du Colombier &mi960, 1203e12c5d1SDavid du Colombier sizeof(Exec), 1213e12c5d1SDavid du Colombier beswal, 1223e12c5d1SDavid du Colombier adotout }, 1233e12c5d1SDavid du Colombier { 0x61010200, /* I960 boot image (little endian) */ 1243e12c5d1SDavid du Colombier "960 plan 9 boot image", 1253e12c5d1SDavid du Colombier FI960B, 1263e12c5d1SDavid du Colombier &mi960, 1273e12c5d1SDavid du Colombier sizeof(struct i960exec), 1283e12c5d1SDavid du Colombier leswal, 1293e12c5d1SDavid du Colombier i960boot }, 130*219b2ee8SDavid du Colombier { X_MAGIC, /* 3210 x.out */ 131*219b2ee8SDavid du Colombier "3210 plan 9 executable", 132*219b2ee8SDavid du Colombier F3210, 133*219b2ee8SDavid du Colombier &m3210, 1343e12c5d1SDavid du Colombier sizeof(Exec), 1353e12c5d1SDavid du Colombier beswal, 1363e12c5d1SDavid du Colombier adotout }, 1373e12c5d1SDavid du Colombier { 0 }, 1383e12c5d1SDavid du Colombier }; 1393e12c5d1SDavid du Colombier 1403e12c5d1SDavid du Colombier Mach *mach = &mmips; /* Global current machine table */ 1413e12c5d1SDavid du Colombier 1423e12c5d1SDavid du Colombier int 1433e12c5d1SDavid du Colombier crackhdr(int fd, Fhdr *fp) 1443e12c5d1SDavid du Colombier { 1453e12c5d1SDavid du Colombier ExecTable *mp; 1463e12c5d1SDavid du Colombier ExecHdr d; 1473e12c5d1SDavid du Colombier int nb, magic; 1483e12c5d1SDavid du Colombier 1493e12c5d1SDavid du Colombier fp->type = FNONE; 1503e12c5d1SDavid du Colombier if ((nb = read(fd, (char *)&d.e, sizeof(d.e))) <= 0) 1513e12c5d1SDavid du Colombier return 0; 1523e12c5d1SDavid du Colombier fp->magic = magic = beswal(d.e.magic); /* big-endian */ 1533e12c5d1SDavid du Colombier for (mp = exectab; mp->magic; mp++) { 1543e12c5d1SDavid du Colombier if (mp->magic == magic && nb >= mp->hsize) { 1553e12c5d1SDavid du Colombier hswal((long *) &d, sizeof(d.e)/sizeof(long), mp->swal); 1563e12c5d1SDavid du Colombier fp->type = mp->type; 1573e12c5d1SDavid du Colombier fp->name = mp->name; 158*219b2ee8SDavid du Colombier fp->hdrsz = mp->hsize; /* zero on bootables */ 1593e12c5d1SDavid du Colombier mach = mp->mach; 1603e12c5d1SDavid du Colombier mp->hparse(fp, &d); 1613e12c5d1SDavid du Colombier seek(fd, mp->hsize, 0); /* seek to end of header */ 1623e12c5d1SDavid du Colombier return 1; 1633e12c5d1SDavid du Colombier } 1643e12c5d1SDavid du Colombier } 1653e12c5d1SDavid du Colombier return 0; 1663e12c5d1SDavid du Colombier } 1673e12c5d1SDavid du Colombier /* 1683e12c5d1SDavid du Colombier * Convert header to canonical form 1693e12c5d1SDavid du Colombier */ 1703e12c5d1SDavid du Colombier static void 1713e12c5d1SDavid du Colombier hswal(long *lp, int n, long (*swap) (long)) 1723e12c5d1SDavid du Colombier { 1733e12c5d1SDavid du Colombier while (n--) { 1743e12c5d1SDavid du Colombier *lp = (*swap) (*lp); 1753e12c5d1SDavid du Colombier lp++; 1763e12c5d1SDavid du Colombier } 1773e12c5d1SDavid du Colombier } 1783e12c5d1SDavid du Colombier /* 1793e12c5d1SDavid du Colombier * Crack a normal a.out-type header 1803e12c5d1SDavid du Colombier */ 1813e12c5d1SDavid du Colombier static void 1823e12c5d1SDavid du Colombier adotout(Fhdr *fp, ExecHdr *hp) 1833e12c5d1SDavid du Colombier { 1843e12c5d1SDavid du Colombier long pgsize = mach->pgsize; 1853e12c5d1SDavid du Colombier 186*219b2ee8SDavid du Colombier settext(fp, hp->e.entry, pgsize+sizeof(Exec), 187*219b2ee8SDavid du Colombier hp->e.text, sizeof(Exec)); 188*219b2ee8SDavid du Colombier setdata(fp, _round(pgsize+fp->txtsz+sizeof(Exec), pgsize), 189*219b2ee8SDavid du Colombier hp->e.data, fp->txtsz+sizeof(Exec), hp->e.bss); 1903e12c5d1SDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 1913e12c5d1SDavid du Colombier } 1923e12c5d1SDavid du Colombier 1933e12c5d1SDavid du Colombier /* 1943e12c5d1SDavid du Colombier * 68020 2.out and 68020 bootable images 1953e12c5d1SDavid du Colombier * 386I 8.out and 386I bootable images 1963e12c5d1SDavid du Colombier * 1973e12c5d1SDavid du Colombier */ 1983e12c5d1SDavid du Colombier static void 1993e12c5d1SDavid du Colombier common(Fhdr *fp, ExecHdr *hp) 2003e12c5d1SDavid du Colombier { 2013e12c5d1SDavid du Colombier long kbase = mach->kbase; 2023e12c5d1SDavid du Colombier 2033e12c5d1SDavid du Colombier adotout(fp, hp); 2043e12c5d1SDavid du Colombier if (fp->entry & kbase) { /* Boot image */ 2053e12c5d1SDavid du Colombier switch(fp->type) { 2063e12c5d1SDavid du Colombier case F68020: 2073e12c5d1SDavid du Colombier fp->type = F68020B; 2083e12c5d1SDavid du Colombier fp->name = "68020 plan 9 boot image"; 209*219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 2103e12c5d1SDavid du Colombier break; 2113e12c5d1SDavid du Colombier case FI386: 2123e12c5d1SDavid du Colombier fp->type = FI386B; 213*219b2ee8SDavid du Colombier fp->txtaddr = sizeof(Exec); 2143e12c5d1SDavid du Colombier fp->name = "386 plan 9 boot image"; 215*219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 216*219b2ee8SDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 2173e12c5d1SDavid du Colombier break; 2183e12c5d1SDavid du Colombier default: 2193e12c5d1SDavid du Colombier break; 2203e12c5d1SDavid du Colombier } 2213e12c5d1SDavid du Colombier fp->txtaddr |= kbase; 2223e12c5d1SDavid du Colombier fp->entry |= kbase; 2233e12c5d1SDavid du Colombier fp->dataddr |= kbase; 2243e12c5d1SDavid du Colombier } 2253e12c5d1SDavid du Colombier } 2263e12c5d1SDavid du Colombier 2273e12c5d1SDavid du Colombier /* 2283e12c5d1SDavid du Colombier * mips bootable image. 2293e12c5d1SDavid du Colombier */ 2303e12c5d1SDavid du Colombier static void 2313e12c5d1SDavid du Colombier mipsboot(Fhdr *fp, ExecHdr *hp) 2323e12c5d1SDavid du Colombier { 2333e12c5d1SDavid du Colombier switch(hp->e.amagic) { 2343e12c5d1SDavid du Colombier default: 2353e12c5d1SDavid du Colombier case 0407: /* some kind of mips */ 2363e12c5d1SDavid du Colombier fp->type = FMIPSB; 2373e12c5d1SDavid du Colombier settext(fp, hp->e.mentry, hp->e.text_start, hp->e.tsize, 2383e12c5d1SDavid du Colombier sizeof(struct mipsexec)+4); 2393e12c5d1SDavid du Colombier setdata(fp, hp->e.data_start, hp->e.dsize, 2403e12c5d1SDavid du Colombier fp->txtoff+hp->e.tsize, hp->e.bsize); 2413e12c5d1SDavid du Colombier break; 2423e12c5d1SDavid du Colombier case 0413: /* some kind of mips */ 2433e12c5d1SDavid du Colombier fp->type = FMIPSB; 2443e12c5d1SDavid du Colombier settext(fp, hp->e.mentry, hp->e.text_start, hp->e.tsize, 0); 2453e12c5d1SDavid du Colombier setdata(fp, hp->e.data_start, hp->e.dsize, hp->e.tsize, 2463e12c5d1SDavid du Colombier hp->e.bsize); 2473e12c5d1SDavid du Colombier break; 2483e12c5d1SDavid du Colombier } 2493e12c5d1SDavid du Colombier setsym(fp, hp->e.nsyms, 0, hp->e.pcsize, hp->e.symptr); 250*219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 2513e12c5d1SDavid du Colombier } 252*219b2ee8SDavid du Colombier 2533e12c5d1SDavid du Colombier /* 254*219b2ee8SDavid du Colombier * mips4k bootable image. 2553e12c5d1SDavid du Colombier */ 2563e12c5d1SDavid du Colombier static void 257*219b2ee8SDavid du Colombier mips4kboot(Fhdr *fp, ExecHdr *hp) 2583e12c5d1SDavid du Colombier { 259*219b2ee8SDavid du Colombier switch(hp->e.h.amagic) { 260*219b2ee8SDavid du Colombier default: 261*219b2ee8SDavid du Colombier case 0407: /* some kind of mips */ 262*219b2ee8SDavid du Colombier fp->type = FMIPSB; 263*219b2ee8SDavid du Colombier settext(fp, hp->e.h.mentry, hp->e.h.text_start, hp->e.h.tsize, 264*219b2ee8SDavid du Colombier sizeof(struct mips4kexec)); 265*219b2ee8SDavid du Colombier setdata(fp, hp->e.h.data_start, hp->e.h.dsize, 266*219b2ee8SDavid du Colombier fp->txtoff+hp->e.h.tsize, hp->e.h.bsize); 267*219b2ee8SDavid du Colombier break; 268*219b2ee8SDavid du Colombier case 0413: /* some kind of mips */ 269*219b2ee8SDavid du Colombier fp->type = FMIPSB; 270*219b2ee8SDavid du Colombier settext(fp, hp->e.h.mentry, hp->e.h.text_start, hp->e.h.tsize, 0); 271*219b2ee8SDavid du Colombier setdata(fp, hp->e.h.data_start, hp->e.h.dsize, hp->e.h.tsize, 272*219b2ee8SDavid du Colombier hp->e.h.bsize); 273*219b2ee8SDavid du Colombier break; 2743e12c5d1SDavid du Colombier } 275*219b2ee8SDavid du Colombier setsym(fp, hp->e.h.nsyms, 0, hp->e.h.pcsize, hp->e.h.symptr); 276*219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 277*219b2ee8SDavid du Colombier } 278*219b2ee8SDavid du Colombier 2793e12c5d1SDavid du Colombier /* 2803e12c5d1SDavid du Colombier * sparc bootable image 2813e12c5d1SDavid du Colombier */ 2823e12c5d1SDavid du Colombier static void 2833e12c5d1SDavid du Colombier sparcboot(Fhdr *fp, ExecHdr *hp) 2843e12c5d1SDavid du Colombier { 2853e12c5d1SDavid du Colombier fp->type = FSPARCB; 2863e12c5d1SDavid du Colombier settext(fp, hp->e.sentry, hp->e.sentry, hp->e.stext, 2873e12c5d1SDavid du Colombier sizeof(struct sparcexec)); 2883e12c5d1SDavid du Colombier setdata(fp, hp->e.sentry+hp->e.stext, hp->e.sdata, 2893e12c5d1SDavid du Colombier fp->txtoff+hp->e.stext, hp->e.sbss); 2903e12c5d1SDavid du Colombier setsym(fp, hp->e.ssyms, 0, hp->e.sdrsize, fp->datoff+hp->e.sdata); 291*219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 2923e12c5d1SDavid du Colombier } 2933e12c5d1SDavid du Colombier 2943e12c5d1SDavid du Colombier /* 2953e12c5d1SDavid du Colombier * next bootable image 2963e12c5d1SDavid du Colombier */ 2973e12c5d1SDavid du Colombier static void 2983e12c5d1SDavid du Colombier nextboot(Fhdr *fp, ExecHdr *hp) 2993e12c5d1SDavid du Colombier { 3003e12c5d1SDavid du Colombier fp->type = FNEXTB; 3013e12c5d1SDavid du Colombier settext(fp, hp->e.textc.vmaddr, hp->e.textc.vmaddr, 3023e12c5d1SDavid du Colombier hp->e.texts.size, hp->e.texts.offset); 3033e12c5d1SDavid du Colombier setdata(fp, hp->e.datac.vmaddr, hp->e.datas.size, 3043e12c5d1SDavid du Colombier hp->e.datas.offset, hp->e.bsss.size); 3053e12c5d1SDavid du Colombier setsym(fp, hp->e.symc.nsyms, hp->e.symc.spoff, hp->e.symc.pcoff, 3063e12c5d1SDavid du Colombier hp->e.symc.symoff); 307*219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 3083e12c5d1SDavid du Colombier } 3093e12c5d1SDavid du Colombier 3103e12c5d1SDavid du Colombier /* 3113e12c5d1SDavid du Colombier * I960 bootable image 3123e12c5d1SDavid du Colombier */ 3133e12c5d1SDavid du Colombier static void 3143e12c5d1SDavid du Colombier i960boot(Fhdr *fp, ExecHdr *hp) 3153e12c5d1SDavid du Colombier { 3163e12c5d1SDavid du Colombier /* long n = hp->e.i6comments.fptrlineno-hp->e.i6comments.fptrreloc; */ 3173e12c5d1SDavid du Colombier 3183e12c5d1SDavid du Colombier settext(fp, hp->e.i6entry, hp->e.i6texts.virt, hp->e.i6texts.size, 3193e12c5d1SDavid du Colombier hp->e.i6texts.fptr); 3203e12c5d1SDavid du Colombier setdata(fp, hp->e.i6datas.virt, hp->e.i6datas.size, 3213e12c5d1SDavid du Colombier hp->e.i6datas.fptr, hp->e.i6bsssize); 3223e12c5d1SDavid du Colombier setsym(fp, 0, 0, 0, 0); 3233e12c5d1SDavid du Colombier /*setsym(fp, n, 0, hp->e.i6comments.size-n, hp->e.i6comments.fptr); */ 324*219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 3253e12c5d1SDavid du Colombier } 3263e12c5d1SDavid du Colombier 3273e12c5d1SDavid du Colombier 3283e12c5d1SDavid du Colombier static void 3293e12c5d1SDavid du Colombier settext(Fhdr *fp, long e, long a, long s, long off) 3303e12c5d1SDavid du Colombier { 3313e12c5d1SDavid du Colombier fp->txtaddr = a; 3323e12c5d1SDavid du Colombier fp->entry = e; 3333e12c5d1SDavid du Colombier fp->txtsz = s; 3343e12c5d1SDavid du Colombier fp->txtoff = off; 3353e12c5d1SDavid du Colombier } 3363e12c5d1SDavid du Colombier static void 3373e12c5d1SDavid du Colombier setdata(Fhdr *fp, long a, long s, long off, long bss) 3383e12c5d1SDavid du Colombier { 3393e12c5d1SDavid du Colombier fp->dataddr = a; 3403e12c5d1SDavid du Colombier fp->datsz = s; 3413e12c5d1SDavid du Colombier fp->datoff = off; 3423e12c5d1SDavid du Colombier fp->bsssz = bss; 3433e12c5d1SDavid du Colombier } 3443e12c5d1SDavid du Colombier static void 3453e12c5d1SDavid du Colombier setsym(Fhdr *fp, long sy, long sppc, long lnpc, long symoff) 3463e12c5d1SDavid du Colombier { 3473e12c5d1SDavid du Colombier fp->symsz = sy; 3483e12c5d1SDavid du Colombier fp->symoff = symoff; 3493e12c5d1SDavid du Colombier fp->sppcsz = sppc; 3503e12c5d1SDavid du Colombier fp->sppcoff = fp->symoff+fp->symsz; 3513e12c5d1SDavid du Colombier fp->lnpcsz = lnpc; 3523e12c5d1SDavid du Colombier fp->lnpcoff = fp->sppcoff+fp->sppcsz; 3533e12c5d1SDavid du Colombier } 3543e12c5d1SDavid du Colombier 355*219b2ee8SDavid du Colombier 356*219b2ee8SDavid du Colombier static long 357*219b2ee8SDavid du Colombier _round(long a, long b) 358*219b2ee8SDavid du Colombier { 359*219b2ee8SDavid du Colombier long w; 360*219b2ee8SDavid du Colombier 361*219b2ee8SDavid du Colombier w = (a/b)*b; 362*219b2ee8SDavid du Colombier if (a!=w) 363*219b2ee8SDavid du Colombier w += b; 364*219b2ee8SDavid du Colombier return(w); 365*219b2ee8SDavid du Colombier } 366