/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * load kernel into memory */#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "ureg.h"#include "pool.h"#include "../port/netif.h"#include "../ip/ip.h"#include "pxe.h" #include <a.out.h>#include "/sys/src/libmach/elf.h" #undef KADDR#undef PADDR #define KADDR(a) ((void*)((ulong)(a) | KZERO))#define PADDR(a) ((ulong)(a) & ~KSEGM) extern int debug; extern void pagingoff(ulong); static uchar elfident[] = { '\177', 'E', 'L', 'F',};static Ehdr ehdr, rehdr;static E64hdr e64hdr;static Phdr *phdr;static P64hdr *p64hdr; static int curphdr;static ulong curoff;static ulong elftotal; static uvlong (*swav)(uvlong);static long (*swal)(long);static ushort (*swab)(ushort); /* * big-endian short */ushortbeswab(ushort s){ uchar *p; p = (uchar*)&s; return (p[0]<<8) | p[1];} /* * big-endian long */longbeswal(long l){ uchar *p; p = (uchar*)&l; return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];} /* * big-endian vlong */uvlongbeswav(uvlong v){ uchar *p; p = (uchar*)&v; return ((uvlong)p[0]<<56) | ((uvlong)p[1]<<48) | ((uvlong)p[2]<<40) | ((uvlong)p[3]<<32) | ((uvlong)p[4]<<24) | ((uvlong)p[5]<<16) | ((uvlong)p[6]<<8) | (uvlong)p[7];} /* * little-endian short */ushortleswab(ushort s){ uchar *p; p = (uchar*)&s; return (p[1]<<8) | p[0];} /* * little-endian long */longleswal(long l){ uchar *p; p = (uchar*)&l; return (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];} /* * little-endian vlong */uvlongleswav(uvlong v){ uchar *p; p = (uchar*)&v; return ((uvlong)p[7]<<56) | ((uvlong)p[6]<<48) | ((uvlong)p[5]<<40) | ((uvlong)p[4]<<32) | ((uvlong)p[3]<<24) | ((uvlong)p[2]<<16) | ((uvlong)p[1]<<8) | (uvlong)p[0];} /* * Convert header to canonical form */static voidhswal(long *lp, int n, long (*swap) (long)){ while (n--) { *lp = (*swap) (*lp); lp++; }} static voidhswav(uvlong *lp, int n, uvlong (*swap)(uvlong)){ while (n--) { *lp = (*swap)(*lp); lp++; }} static intreadehdr(Boot *b){ int i; /* bitswap the header according to the DATA format */ if(ehdr.ident[CLASS] != ELFCLASS32) { print("bad ELF class - not 32 bit\n"); return 0; } if(ehdr.ident[DATA] == ELFDATA2LSB) { swab = leswab; swal = leswal; } else if(ehdr.ident[DATA] == ELFDATA2MSB) { swab = beswab; swal = beswal; } else { print("bad ELF encoding - not big or little endian\n"); return 0; } memmove(&rehdr, &ehdr, sizeof(Ehdr)); /* copy; never used */ ehdr.type = swab(ehdr.type); ehdr.machine = swab(ehdr.machine); ehdr.version = swal(ehdr.version); ehdr.elfentry = swal(ehdr.elfentry); ehdr.phoff = swal(ehdr.phoff); ehdr.shoff = swal(ehdr.shoff); ehdr.flags = swal(ehdr.flags); ehdr.ehsize = swab(ehdr.ehsize); ehdr.phentsize = swab(ehdr.phentsize); ehdr.phnum = swab(ehdr.phnum); ehdr.shentsize = swab(ehdr.shentsize); ehdr.shnum = swab(ehdr.shnum); ehdr.shstrndx = swab(ehdr.shstrndx); if(ehdr.type != EXEC || ehdr.version != CURRENT) return 0; if(ehdr.phentsize != sizeof(Phdr)) return 0; if(debug) print("readehdr OK entry %#lux\n", ehdr.elfentry); curoff = sizeof(Ehdr); i = ehdr.phoff+ehdr.phentsize*ehdr.phnum - curoff; b->state = READPHDR; b->bp = (char*)smalloc(i); b->wp = b->bp; b->ep = b->wp + i; elftotal = 0; phdr = (Phdr*)(b->bp + ehdr.phoff-sizeof(Ehdr)); if(debug) print("phdr..."); return 1;} static intreade64hdr(Boot *b){ int i; /* bitswap the header according to the DATA format */ if(e64hdr.ident[CLASS] != ELFCLASS64) { print("bad ELF class - not 64 bit\n"); return 0; } if(e64hdr.ident[DATA] == ELFDATA2LSB) { swab = leswab; swal = leswal; swav = leswav; } else if(e64hdr.ident[DATA] == ELFDATA2MSB) { swab = beswab; swal = beswal; swav = beswav; } else { print("bad ELF encoding - not big or little endian\n"); return 0; }// memmove(&rehdr, &ehdr, sizeof(Ehdr)); /* copy; never used */ e64hdr.type = swab(e64hdr.type); e64hdr.machine = swab(e64hdr.machine); e64hdr.version = swal(e64hdr.version); e64hdr.elfentry = swav(e64hdr.elfentry); e64hdr.phoff = swav(e64hdr.phoff); e64hdr.shoff = swav(e64hdr.shoff); e64hdr.flags = swal(e64hdr.flags); e64hdr.ehsize = swab(e64hdr.ehsize); e64hdr.phentsize = swab(e64hdr.phentsize); e64hdr.phnum = swab(e64hdr.phnum); e64hdr.shentsize = swab(e64hdr.shentsize); e64hdr.shnum = swab(e64hdr.shnum); e64hdr.shstrndx = swab(e64hdr.shstrndx); if(e64hdr.type != EXEC || e64hdr.version != CURRENT) return 0; if(e64hdr.phentsize != sizeof(P64hdr)) return 0; if(debug) print("reade64hdr OK entry %#llux\n", e64hdr.elfentry); curoff = sizeof(E64hdr); i = e64hdr.phoff + e64hdr.phentsize*e64hdr.phnum - curoff; b->state = READ64PHDR; b->bp = (char*)smalloc(i); b->wp = b->bp; b->ep = b->wp + i; elftotal = 0; p64hdr = (P64hdr*)(b->bp + e64hdr.phoff-sizeof(E64hdr)); if(debug) print("p64hdr..."); return 1;} static intnextphdr(Boot *b){ Phdr *php; ulong offset; char *physaddr; if(debug) print("readedata %d\n", curphdr); for(; curphdr < ehdr.phnum; curphdr++){ php = phdr+curphdr; if(php->type != LOAD) continue; offset = php->offset; physaddr = (char*)KADDR(PADDR(php->paddr)); if(offset < curoff){ /* * Can't (be bothered to) rewind the * input, it might be from tftp. If we * did then we could boot FreeBSD kernels * too maybe. */ return 0; } if(php->offset > curoff){ b->state = READEPAD; b->bp = (char*)smalloc(offset - curoff); b->wp = b->bp; b->ep = b->wp + offset - curoff; if(debug) print("nextphdr %lud...\n", offset - curoff); return 1; } b->state = READEDATA; b->bp = physaddr; b->wp = b->bp; b->ep = b->wp+php->filesz; print("%ud+", php->filesz); elftotal += php->filesz; if(debug) print("nextphdr %ud@%#p\n", php->filesz, physaddr); return 1; } if(curphdr != 0){ print("=%lud\n", elftotal); b->state = TRYEBOOT; b->entry = ehdr.elfentry; // PLLONG(b->hdr.entry, b->entry); return 1; } return 0;} static intnextp64hdr(Boot *b){ P64hdr *php; uvlong offset; char *physaddr; if(debug) print("reade64data %d\n", curphdr); for(; curphdr < e64hdr.phnum; curphdr++){ php = p64hdr+curphdr; if(php->type != LOAD) continue; offset = php->offset; physaddr = (char*)KADDR(PADDR(php->paddr)); if(offset < curoff){ /* * Can't (be bothered to) rewind the * input, it might be from tftp. If we * did then we could boot FreeBSD kernels * too maybe. */ return 0; } if(php->offset > curoff){ b->state = READE64PAD; b->bp = (char*)smalloc(offset - curoff); b->wp = b->bp; b->ep = b->wp + offset - curoff; if(debug) print("nextp64hdr %llud...\n", offset - curoff); return 1; } b->state = READE64DATA; b->bp = physaddr; b->wp = b->bp; b->ep = b->wp+php->filesz; print("%llud+", php->filesz); elftotal += php->filesz; if(debug) print("nextp64hdr %llud@%#p\n", php->filesz, physaddr); return 1; } if(curphdr != 0){ print("=%lud\n", elftotal); b->state = TRYE64BOOT; b->entry = e64hdr.elfentry; return 1; } return 0;} static intreadepad(Boot *b){ Phdr *php; php = phdr+curphdr; if(debug) print("readepad %d\n", curphdr); curoff = php->offset; return nextphdr(b);} static intreade64pad(Boot *b){ P64hdr *php; php = p64hdr+curphdr; if(debug) print("reade64pad %d\n", curphdr); curoff = php->offset; return nextp64hdr(b);} static intreadedata(Boot *b){ Phdr *php; php = phdr+curphdr; if(debug) print("readedata %d\n", curphdr); if(php->filesz < php->memsz){ print("%lud", php->memsz-php->filesz); elftotal += php->memsz-php->filesz; memset((char*)KADDR(PADDR(php->paddr)+php->filesz), 0, php->memsz-php->filesz); } curoff = php->offset+php->filesz; curphdr++; return nextphdr(b);} static intreade64data(Boot *b){ P64hdr *php; php = p64hdr+curphdr; if(debug) print("reade64data %d\n", curphdr); if(php->filesz < php->memsz){ print("%llud", php->memsz - php->filesz); elftotal += php->memsz - php->filesz; memset((char*)KADDR(PADDR(php->paddr) + php->filesz), 0, php->memsz - php->filesz); } curoff = php->offset + php->filesz; curphdr++; return nextp64hdr(b);} static intreadphdr(Boot *b){ Phdr *php; php = phdr; hswal((long*)php, ehdr.phentsize*ehdr.phnum/sizeof(long), swal); if(debug) print("phdr curoff %lud vaddr %#lux paddr %#lux\n", curoff, php->vaddr, php->paddr); curoff = ehdr.phoff+ehdr.phentsize*ehdr.phnum; curphdr = 0; return nextphdr(b);} static intreadp64hdr(Boot *b){ int hdr; P64hdr *php, *p; php = p = p64hdr; for (hdr = 0; hdr < e64hdr.phnum; hdr++, p++) { hswal((long*)p, 2, swal); hswav((uvlong*)&p->offset, 6, swav); } if(debug) print("p64hdr curoff %lud vaddr %#llux paddr %#llux\n", curoff, php->vaddr, php->paddr); curoff = e64hdr.phoff + e64hdr.phentsize*e64hdr.phnum; curphdr = 0; return nextp64hdr(b);} static intaddbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf){ int n; n = edbuf - *dbuf; if(n <= 0) return 0; /* dest buffer is full */ if(n > esbuf - *sbuf) n = esbuf - *sbuf; if(n <= 0) return -1; /* src buffer is empty */ memmove(*dbuf, *sbuf, n); *sbuf += n;Lines 1–500 of 858. Load more
/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * load kernel into memory */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" #include "pool.h" #include "../port/netif.h" #include "../ip/ip.h" #include "pxe.h" #include <a.out.h> #include "/sys/src/libmach/elf.h" #undef KADDR #undef PADDR #define KADDR(a) ((void*)((ulong)(a) | KZERO)) #define PADDR(a) ((ulong)(a) & ~KSEGM) extern int debug; extern void pagingoff(ulong); static uchar elfident[] = { '\177', 'E', 'L', 'F', }; static Ehdr ehdr, rehdr; static E64hdr e64hdr; static Phdr *phdr; static P64hdr *p64hdr; static int curphdr; static ulong curoff; static ulong elftotal; static uvlong (*swav)(uvlong); static long (*swal)(long); static ushort (*swab)(ushort); /* * big-endian short */ ushort beswab(ushort s) { uchar *p; p = (uchar*)&s; return (p[0]<<8) | p[1]; } /* * big-endian long */ long beswal(long l) { uchar *p; p = (uchar*)&l; return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; } /* * big-endian vlong */ uvlong beswav(uvlong v) { uchar *p; p = (uchar*)&v; return ((uvlong)p[0]<<56) | ((uvlong)p[1]<<48) | ((uvlong)p[2]<<40) | ((uvlong)p[3]<<32) | ((uvlong)p[4]<<24) | ((uvlong)p[5]<<16) | ((uvlong)p[6]<<8) | (uvlong)p[7]; } /* * little-endian short */ ushort leswab(ushort s) { uchar *p; p = (uchar*)&s; return (p[1]<<8) | p[0]; } /* * little-endian long */ long leswal(long l) { uchar *p; p = (uchar*)&l; return (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0]; } /* * little-endian vlong */ uvlong leswav(uvlong v) { uchar *p; p = (uchar*)&v; return ((uvlong)p[7]<<56) | ((uvlong)p[6]<<48) | ((uvlong)p[5]<<40) | ((uvlong)p[4]<<32) | ((uvlong)p[3]<<24) | ((uvlong)p[2]<<16) | ((uvlong)p[1]<<8) | (uvlong)p[0]; } /* * Convert header to canonical form */ static void hswal(long *lp, int n, long (*swap) (long)) { while (n--) { *lp = (*swap) (*lp); lp++; } } static void hswav(uvlong *lp, int n, uvlong (*swap)(uvlong)) { while (n--) { *lp = (*swap)(*lp); lp++; } } static int readehdr(Boot *b) { int i; /* bitswap the header according to the DATA format */ if(ehdr.ident[CLASS] != ELFCLASS32) { print("bad ELF class - not 32 bit\n"); return 0; } if(ehdr.ident[DATA] == ELFDATA2LSB) { swab = leswab; swal = leswal; } else if(ehdr.ident[DATA] == ELFDATA2MSB) { swab = beswab; swal = beswal; } else { print("bad ELF encoding - not big or little endian\n"); return 0; } memmove(&rehdr, &ehdr, sizeof(Ehdr)); /* copy; never used */ ehdr.type = swab(ehdr.type); ehdr.machine = swab(ehdr.machine); ehdr.version = swal(ehdr.version); ehdr.elfentry = swal(ehdr.elfentry); ehdr.phoff = swal(ehdr.phoff); ehdr.shoff = swal(ehdr.shoff); ehdr.flags = swal(ehdr.flags); ehdr.ehsize = swab(ehdr.ehsize); ehdr.phentsize = swab(ehdr.phentsize); ehdr.phnum = swab(ehdr.phnum); ehdr.shentsize = swab(ehdr.shentsize); ehdr.shnum = swab(ehdr.shnum); ehdr.shstrndx = swab(ehdr.shstrndx); if(ehdr.type != EXEC || ehdr.version != CURRENT) return 0; if(ehdr.phentsize != sizeof(Phdr)) return 0; if(debug) print("readehdr OK entry %#lux\n", ehdr.elfentry); curoff = sizeof(Ehdr); i = ehdr.phoff+ehdr.phentsize*ehdr.phnum - curoff; b->state = READPHDR; b->bp = (char*)smalloc(i); b->wp = b->bp; b->ep = b->wp + i; elftotal = 0; phdr = (Phdr*)(b->bp + ehdr.phoff-sizeof(Ehdr)); if(debug) print("phdr..."); return 1; } static int reade64hdr(Boot *b) { int i; /* bitswap the header according to the DATA format */ if(e64hdr.ident[CLASS] != ELFCLASS64) { print("bad ELF class - not 64 bit\n"); return 0; } if(e64hdr.ident[DATA] == ELFDATA2LSB) { swab = leswab; swal = leswal; swav = leswav; } else if(e64hdr.ident[DATA] == ELFDATA2MSB) { swab = beswab; swal = beswal; swav = beswav; } else { print("bad ELF encoding - not big or little endian\n"); return 0; } // memmove(&rehdr, &ehdr, sizeof(Ehdr)); /* copy; never used */ e64hdr.type = swab(e64hdr.type); e64hdr.machine = swab(e64hdr.machine); e64hdr.version = swal(e64hdr.version); e64hdr.elfentry = swav(e64hdr.elfentry); e64hdr.phoff = swav(e64hdr.phoff); e64hdr.shoff = swav(e64hdr.shoff); e64hdr.flags = swal(e64hdr.flags); e64hdr.ehsize = swab(e64hdr.ehsize); e64hdr.phentsize = swab(e64hdr.phentsize); e64hdr.phnum = swab(e64hdr.phnum); e64hdr.shentsize = swab(e64hdr.shentsize); e64hdr.shnum = swab(e64hdr.shnum); e64hdr.shstrndx = swab(e64hdr.shstrndx); if(e64hdr.type != EXEC || e64hdr.version != CURRENT) return 0; if(e64hdr.phentsize != sizeof(P64hdr)) return 0; if(debug) print("reade64hdr OK entry %#llux\n", e64hdr.elfentry); curoff = sizeof(E64hdr); i = e64hdr.phoff + e64hdr.phentsize*e64hdr.phnum - curoff; b->state = READ64PHDR; b->bp = (char*)smalloc(i); b->wp = b->bp; b->ep = b->wp + i; elftotal = 0; p64hdr = (P64hdr*)(b->bp + e64hdr.phoff-sizeof(E64hdr)); if(debug) print("p64hdr..."); return 1; } static int nextphdr(Boot *b) { Phdr *php; ulong offset; char *physaddr; if(debug) print("readedata %d\n", curphdr); for(; curphdr < ehdr.phnum; curphdr++){ php = phdr+curphdr; if(php->type != LOAD) continue; offset = php->offset; physaddr = (char*)KADDR(PADDR(php->paddr)); if(offset < curoff){ /* * Can't (be bothered to) rewind the * input, it might be from tftp. If we * did then we could boot FreeBSD kernels * too maybe. */ return 0; } if(php->offset > curoff){ b->state = READEPAD; b->bp = (char*)smalloc(offset - curoff); b->wp = b->bp; b->ep = b->wp + offset - curoff; if(debug) print("nextphdr %lud...\n", offset - curoff); return 1; } b->state = READEDATA; b->bp = physaddr; b->wp = b->bp; b->ep = b->wp+php->filesz; print("%ud+", php->filesz); elftotal += php->filesz; if(debug) print("nextphdr %ud@%#p\n", php->filesz, physaddr); return 1; } if(curphdr != 0){ print("=%lud\n", elftotal); b->state = TRYEBOOT; b->entry = ehdr.elfentry; // PLLONG(b->hdr.entry, b->entry); return 1; } return 0; } static int nextp64hdr(Boot *b) { P64hdr *php; uvlong offset; char *physaddr; if(debug) print("reade64data %d\n", curphdr); for(; curphdr < e64hdr.phnum; curphdr++){ php = p64hdr+curphdr; if(php->type != LOAD) continue; offset = php->offset; physaddr = (char*)KADDR(PADDR(php->paddr)); if(offset < curoff){ /* * Can't (be bothered to) rewind the * input, it might be from tftp. If we * did then we could boot FreeBSD kernels * too maybe. */ return 0; } if(php->offset > curoff){ b->state = READE64PAD; b->bp = (char*)smalloc(offset - curoff); b->wp = b->bp; b->ep = b->wp + offset - curoff; if(debug) print("nextp64hdr %llud...\n", offset - curoff); return 1; } b->state = READE64DATA; b->bp = physaddr; b->wp = b->bp; b->ep = b->wp+php->filesz; print("%llud+", php->filesz); elftotal += php->filesz; if(debug) print("nextp64hdr %llud@%#p\n", php->filesz, physaddr); return 1; } if(curphdr != 0){ print("=%lud\n", elftotal); b->state = TRYE64BOOT; b->entry = e64hdr.elfentry; return 1; } return 0; } static int readepad(Boot *b) { Phdr *php; php = phdr+curphdr; if(debug) print("readepad %d\n", curphdr); curoff = php->offset; return nextphdr(b); } static int reade64pad(Boot *b) { P64hdr *php; php = p64hdr+curphdr; if(debug) print("reade64pad %d\n", curphdr); curoff = php->offset; return nextp64hdr(b); } static int readedata(Boot *b) { Phdr *php; php = phdr+curphdr; if(debug) print("readedata %d\n", curphdr); if(php->filesz < php->memsz){ print("%lud", php->memsz-php->filesz); elftotal += php->memsz-php->filesz; memset((char*)KADDR(PADDR(php->paddr)+php->filesz), 0, php->memsz-php->filesz); } curoff = php->offset+php->filesz; curphdr++; return nextphdr(b); } static int reade64data(Boot *b) { P64hdr *php; php = p64hdr+curphdr; if(debug) print("reade64data %d\n", curphdr); if(php->filesz < php->memsz){ print("%llud", php->memsz - php->filesz); elftotal += php->memsz - php->filesz; memset((char*)KADDR(PADDR(php->paddr) + php->filesz), 0, php->memsz - php->filesz); } curoff = php->offset + php->filesz; curphdr++; return nextp64hdr(b); } static int readphdr(Boot *b) { Phdr *php; php = phdr; hswal((long*)php, ehdr.phentsize*ehdr.phnum/sizeof(long), swal); if(debug) print("phdr curoff %lud vaddr %#lux paddr %#lux\n", curoff, php->vaddr, php->paddr); curoff = ehdr.phoff+ehdr.phentsize*ehdr.phnum; curphdr = 0; return nextphdr(b); } static int readp64hdr(Boot *b) { int hdr; P64hdr *php, *p; php = p = p64hdr; for (hdr = 0; hdr < e64hdr.phnum; hdr++, p++) { hswal((long*)p, 2, swal); hswav((uvlong*)&p->offset, 6, swav); } if(debug) print("p64hdr curoff %lud vaddr %#llux paddr %#llux\n", curoff, php->vaddr, php->paddr); curoff = e64hdr.phoff + e64hdr.phentsize*e64hdr.phnum; curphdr = 0; return nextp64hdr(b); } static int addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf) { int n; n = edbuf - *dbuf; if(n <= 0) return 0; /* dest buffer is full */ if(n > esbuf - *sbuf) n = esbuf - *sbuf; if(n <= 0) return -1; /* src buffer is empty */ memmove(*dbuf, *sbuf, n); *sbuf += n;