Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F152510039
D22309.id64155.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D22309.id64155.diff
View Options
Index: stand/common/bootstrap.h
===================================================================
--- stand/common/bootstrap.h
+++ stand/common/bootstrap.h
@@ -257,6 +257,7 @@
typedef Elf_Addr (symaddr_fn)(struct elf_file *ef, Elf_Size symidx);
int __elfN(loadfile)(char *filename, uint64_t dest, struct preloaded_file **result);
+size_t __elfN(obj_imagesize)(void *);
int __elfN(obj_loadfile)(char *filename, uint64_t dest,
struct preloaded_file **result);
int __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr,
Index: stand/common/load_elf_obj.c
===================================================================
--- stand/common/load_elf_obj.c
+++ stand/common/load_elf_obj.c
@@ -144,8 +144,18 @@
goto oerr;
}
+ /* Read in the section headers. */
+ ef.e_shdr = alloc_pread(ef.fd, (off_t)hdr->e_shoff,
+ hdr->e_shnum * hdr->e_shentsize);
+ if (ef.e_shdr == NULL) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "_obj_loadfile: read section headers failed\n");
+ err = errno;
+ goto oerr;
+ }
+
if (archsw.arch_loadaddr != NULL)
- dest = archsw.arch_loadaddr(LOAD_ELF, hdr, dest);
+ dest = archsw.arch_loadaddr(LOAD_ELF, &ef, dest);
else
dest = roundup(dest, PAGE_SIZE);
@@ -188,6 +198,91 @@
return(err);
}
+size_t
+__elfN(obj_imagesize)(void *ptr)
+{
+ elf_file_t ef = ptr;
+ Elf_Ehdr *hdr;
+ Elf_Shdr *shdr;
+ size_t size;
+ int i, nsym, symstrindex;
+
+ hdr = &ef->hdr;
+ shdr = ef->e_shdr;
+ size = 0;
+ for (i = 0; i < hdr->e_shnum; i++) {
+ if (shdr[i].sh_size == 0)
+ continue;
+ switch (shdr[i].sh_type) {
+ case SHT_PROGBITS:
+ case SHT_NOBITS:
+#if defined(__i386__) || defined(__amd64__)
+ case SHT_X86_64_UNWIND:
+#endif
+ if ((shdr[i].sh_flags & SHF_ALLOC) == 0)
+ break;
+ size = roundup(size, shdr[i].sh_addralign);
+ size += shdr[i].sh_size;
+ break;
+ }
+ }
+
+ /* Symbols. */
+ nsym = 0;
+ for (i = 0; i < hdr->e_shnum; i++) {
+ switch (shdr[i].sh_type) {
+ case SHT_SYMTAB:
+ nsym++;
+ ef->symtabindex = i;
+ size += shdr[i].sh_size;
+ break;
+ }
+ }
+ if (nsym != 1) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "_obj_imagesize: file has no valid symbol table\n");
+ goto out;
+ }
+ size = roundup(size, shdr[ef->symtabindex].sh_addralign);
+ size += shdr[ef->symtabindex].sh_size;
+
+ symstrindex = shdr[ef->symtabindex].sh_link;
+ if (symstrindex < 0 || symstrindex >= hdr->e_shnum ||
+ shdr[symstrindex].sh_type != SHT_STRTAB) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "_obj_imagesize: file has invalid symbol strings\n");
+ goto out;
+ }
+ size = roundup(size, shdr[symstrindex].sh_addralign);
+ size += shdr[symstrindex].sh_size;
+
+ /* Section names. */
+ if (hdr->e_shstrndx == 0 || hdr->e_shstrndx >= hdr->e_shnum ||
+ shdr[hdr->e_shstrndx].sh_type != SHT_STRTAB) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "_obj_imagesize: file has no section names\n");
+ goto out;
+ }
+ ef->shstrindex = hdr->e_shstrndx;
+ size = roundup(size, shdr[ef->shstrindex].sh_addralign);
+ size += shdr[ef->shstrindex].sh_size;
+
+ /* Relocation tables. */
+ for (i = 0; i < hdr->e_shnum; i++) {
+ switch (shdr[i].sh_type) {
+ case SHT_REL:
+ case SHT_RELA:
+ if ((shdr[shdr[i].sh_info].sh_flags & SHF_ALLOC) == 0)
+ break;
+ size = roundup(size, shdr[i].sh_addralign);
+ size += shdr[i].sh_size;
+ break;
+ }
+ }
+out:
+ return (size);
+}
+
/*
* With the file (fd) open on the image, and (ehdr) containing
* the Elf header, load the image at (off)
@@ -198,22 +293,14 @@
Elf_Ehdr *hdr;
Elf_Shdr *shdr, *cshdr, *lshdr;
vm_offset_t firstaddr, lastaddr;
- int i, nsym, res, ret, shdrbytes, symstrindex;
+ int i, nsym, res, ret, shdrbytes, symstrindex;
ret = 0;
firstaddr = lastaddr = (vm_offset_t)off;
hdr = &ef->hdr;
+ shdr = ef->e_shdr;
ef->off = (vm_offset_t)off;
-
- /* Read in the section headers. */
shdrbytes = hdr->e_shnum * hdr->e_shentsize;
- shdr = alloc_pread(ef->fd, (off_t)hdr->e_shoff, shdrbytes);
- if (shdr == NULL) {
- printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
- "_obj_loadimage: read section headers failed\n");
- goto out;
- }
- ef->e_shdr = shdr;
/*
* Decide where to load everything, but don't read it yet.
Index: stand/common/misc.c
===================================================================
--- stand/common/misc.c
+++ stand/common/misc.c
@@ -149,6 +149,7 @@
#ifdef DEBUG
printf("\nmalloc(%d) failed\n", (int)len);
#endif
+ errno = ENOMEM;
return (NULL);
}
if (lseek(fd, off, SEEK_SET) == -1) {
Index: stand/i386/libi386/biossmap.c
===================================================================
--- stand/i386/libi386/biossmap.c
+++ stand/i386/libi386/biossmap.c
@@ -119,6 +119,13 @@
}
void
+bios_getsmapdata(u_int *smaplenp, struct bios_smap **smapbasep)
+{
+ *smaplenp = smaplen;
+ *smapbasep = smapbase;
+}
+
+void
bios_addsmapdata(struct preloaded_file *kfp)
{
size_t size;
Index: stand/i386/libi386/i386_copy.c
===================================================================
--- stand/i386/libi386/i386_copy.c
+++ stand/i386/libi386/i386_copy.c
@@ -33,9 +33,133 @@
* XXX should check load address/size against memory top.
*/
#include <stand.h>
-
+#include <sys/param.h>
+#include <machine/elf.h>
+#include "bootstrap.h"
#include "libi386.h"
#include "btxv86.h"
+
+extern size_t elf64_obj_imagesize(void *);
+/*
+ * Verify the address is not in use by existing modules.
+ */
+static vm_offset_t
+addr_verify(struct preloaded_file *fp, vm_offset_t addr, size_t size)
+{
+ vm_offset_t f_addr;
+
+ while (fp != NULL) {
+ f_addr = fp->f_addr;
+
+ if ((f_addr <= addr) &&
+ (f_addr + fp->f_size >= addr)) {
+ return (0);
+ }
+ if ((f_addr >= addr) && (f_addr <= addr + size)) {
+ return (0);
+ }
+ fp = fp->f_next;
+ }
+ return (addr);
+}
+
+/*
+ * Find smap entry above 1MB, able to contain size bytes from addr.
+ */
+static vm_offset_t
+smap_find(struct bios_smap *smap, int smaplen, vm_offset_t addr, size_t size)
+{
+ int i;
+
+ for (i = 0; i < smaplen; i++) {
+ if (smap[i].type != SMAP_TYPE_MEMORY)
+ continue;
+
+ /* We do not want address below 1MB. */
+ if (smap[i].base < 0x100000)
+ continue;
+
+ /* Do we fit into current entry? */
+ if ((smap[i].base <= addr) &&
+ (smap[i].base + smap[i].length >= addr + size)) {
+ return (addr);
+ }
+
+ /* Do we fit into new entry? */
+ if ((smap[i].base > addr) && (smap[i].length >= size)) {
+ return (smap[i].base);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Find usable address for loading. The address for the kernel is fixed, as
+ * it is determined by kernel linker map.
+ * For modules, we need to consult smap, the module address has to be
+ * aligned to page boundary and we have to fit into smap entry.
+ */
+uint64_t
+i386_loadaddr(u_int type, void *data, uint64_t addr)
+{
+ struct stat st;
+ size_t size;
+ struct preloaded_file *fp, *mfp;
+ struct bios_smap *smap;
+ u_int smaplen;
+ vm_offset_t off;
+
+ /*
+ * For now, assume we have memory for the kernel, the
+ * required map is [1MB..) This assumption should be safe with x86 BIOS.
+ */
+ fp = file_findfile(NULL, NULL);
+ if (fp == NULL) {
+ return (roundup(addr, PAGE_SIZE));
+ }
+
+ size = 0;
+ if (type == LOAD_RAW) {
+ stat(data, &st);
+ size = st.st_size;
+ }
+
+ if (type == LOAD_ELF) {
+ Elf_Ehdr *hdr = data;
+
+ if (hdr->e_ident[EI_CLASS] == ELFCLASS64)
+ size = elf64_obj_imagesize(data);
+ else if (hdr->e_ident[EI_CLASS] == ELFCLASS32)
+ size = elf32_obj_imagesize(data);
+ else
+ return (roundup(addr, PAGE_SIZE));
+ }
+ if (size == 0)
+ return (roundup(addr, PAGE_SIZE));
+
+ bios_getsmapdata(&smaplen, &smap);
+
+ /* Start from the end of the kernel. */
+ mfp = fp;
+ do {
+ if (mfp == NULL) {
+ off = roundup2(addr + 1, PAGE_SIZE);
+ } else {
+ off = roundup2(mfp->f_addr + mfp->f_size + 1,
+ PAGE_SIZE);
+ }
+ off = smap_find(smap, smaplen, off, size);
+ off = addr_verify(fp, off, size);
+ if (off != 0)
+ break;
+
+ if (mfp == NULL)
+ break;
+ mfp = mfp->f_next;
+ } while (off == 0);
+
+ return (off);
+}
ssize_t
i386_copyin(const void *src, vm_offset_t dest, const size_t len)
Index: stand/i386/libi386/libi386.h
===================================================================
--- stand/i386/libi386/libi386.h
+++ stand/i386/libi386/libi386.h
@@ -26,6 +26,8 @@
* $FreeBSD$
*/
+#include <sys/cdefs.h>
+#include <machine/pc/bios.h>
/*
* i386 fully-qualified device descriptor.
@@ -108,6 +110,7 @@
struct preloaded_file;
void bios_addsmapdata(struct preloaded_file *);
+void bios_getsmapdata(u_int *, struct bios_smap **);
void bios_getsmap(void);
void bios_getmem(void);
@@ -142,6 +145,7 @@
void biosacpi_detect(void);
int i386_autoload(void);
+uint64_t i386_loadaddr(u_int type, void *data, uint64_t addr);
int bi_getboothowto(char *kargs);
void bi_setboothowto(int howto);
Index: stand/i386/loader/main.c
===================================================================
--- stand/i386/loader/main.c
+++ stand/i386/loader/main.c
@@ -167,6 +167,7 @@
archsw.arch_readin = i386_readin;
archsw.arch_isainb = isa_inb;
archsw.arch_isaoutb = isa_outb;
+ archsw.arch_loadaddr = i386_loadaddr;
archsw.arch_hypervisor = x86_hypervisor;
#ifdef LOADER_ZFS_SUPPORT
archsw.arch_zfs_probe = i386_zfs_probe;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Apr 16, 10:16 AM (1 m, 19 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31534686
Default Alt Text
D22309.id64155.diff (9 KB)
Attached To
Mode
D22309: loader: bios loader should check the smap while loading the modules
Attached
Detach File
Event Timeline
Log In to Comment