18600fd4dSToomas Soome /*
2199767f8SToomas Soome * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3199767f8SToomas Soome * All rights reserved.
4199767f8SToomas Soome *
5199767f8SToomas Soome * Redistribution and use in source and binary forms, with or without
6199767f8SToomas Soome * modification, are permitted provided that the following conditions
7199767f8SToomas Soome * are met:
8199767f8SToomas Soome * 1. Redistributions of source code must retain the above copyright
9199767f8SToomas Soome * notice, this list of conditions and the following disclaimer.
10199767f8SToomas Soome * 2. Redistributions in binary form must reproduce the above copyright
11199767f8SToomas Soome * notice, this list of conditions and the following disclaimer in the
12199767f8SToomas Soome * documentation and/or other materials provided with the distribution.
13199767f8SToomas Soome *
14199767f8SToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15199767f8SToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16199767f8SToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17199767f8SToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18199767f8SToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19199767f8SToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20199767f8SToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21199767f8SToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22199767f8SToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23199767f8SToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24199767f8SToomas Soome * SUCH DAMAGE.
25199767f8SToomas Soome */
26199767f8SToomas Soome
27199767f8SToomas Soome #include <sys/cdefs.h>
28199767f8SToomas Soome
29199767f8SToomas Soome /*
308600fd4dSToomas Soome * MD primitives supporting placement of module data
31199767f8SToomas Soome *
32199767f8SToomas Soome * XXX should check load address/size against memory top.
33199767f8SToomas Soome */
34199767f8SToomas Soome #include <stand.h>
358600fd4dSToomas Soome #include <sys/param.h>
368600fd4dSToomas Soome #include <sys/multiboot2.h>
37cb371639SToomas Soome #include <sys/consplat.h>
388600fd4dSToomas Soome #include <machine/metadata.h>
398600fd4dSToomas Soome #include <machine/pc/bios.h>
40199767f8SToomas Soome #include "libi386.h"
41199767f8SToomas Soome #include "btxv86.h"
428600fd4dSToomas Soome #include "bootstrap.h"
438600fd4dSToomas Soome
44cb371639SToomas Soome extern multiboot_tag_framebuffer_t gfx_fb;
45cb371639SToomas Soome
468600fd4dSToomas Soome /*
478600fd4dSToomas Soome * Verify the address is not in use by existing modules.
488600fd4dSToomas Soome */
498600fd4dSToomas Soome static vm_offset_t
addr_verify(struct preloaded_file * fp,vm_offset_t addr,size_t size)508600fd4dSToomas Soome addr_verify(struct preloaded_file *fp, vm_offset_t addr, size_t size)
518600fd4dSToomas Soome {
528600fd4dSToomas Soome vm_offset_t f_addr;
538600fd4dSToomas Soome
548600fd4dSToomas Soome while (fp != NULL) {
558600fd4dSToomas Soome f_addr = fp->f_addr;
568600fd4dSToomas Soome
578600fd4dSToomas Soome if ((f_addr <= addr) &&
58cb371639SToomas Soome (f_addr + fp->f_size >= addr)) {
598600fd4dSToomas Soome return (0);
608600fd4dSToomas Soome }
618600fd4dSToomas Soome if ((f_addr >= addr) && (f_addr <= addr + size)) {
628600fd4dSToomas Soome return (0);
638600fd4dSToomas Soome }
648600fd4dSToomas Soome fp = fp->f_next;
658600fd4dSToomas Soome }
668600fd4dSToomas Soome return (addr);
678600fd4dSToomas Soome }
688600fd4dSToomas Soome
698600fd4dSToomas Soome /*
708600fd4dSToomas Soome * Find smap entry above 1MB, able to contain size bytes from addr.
718600fd4dSToomas Soome */
728600fd4dSToomas Soome static vm_offset_t
smap_find(struct bios_smap * smap,int smaplen,vm_offset_t addr,size_t size)738600fd4dSToomas Soome smap_find(struct bios_smap *smap, int smaplen, vm_offset_t addr, size_t size)
748600fd4dSToomas Soome {
758600fd4dSToomas Soome int i;
768600fd4dSToomas Soome
778600fd4dSToomas Soome for (i = 0; i < smaplen; i++) {
788600fd4dSToomas Soome if (smap[i].type != SMAP_TYPE_MEMORY)
798600fd4dSToomas Soome continue;
808600fd4dSToomas Soome
818600fd4dSToomas Soome /* We do not want address below 1MB. */
828600fd4dSToomas Soome if (smap[i].base < 0x100000)
838600fd4dSToomas Soome continue;
848600fd4dSToomas Soome
858600fd4dSToomas Soome /* Do we fit into current entry? */
868600fd4dSToomas Soome if ((smap[i].base <= addr) &&
878600fd4dSToomas Soome (smap[i].base + smap[i].length >= addr + size)) {
888600fd4dSToomas Soome return (addr);
898600fd4dSToomas Soome }
908600fd4dSToomas Soome
918600fd4dSToomas Soome /* Do we fit into new entry? */
928600fd4dSToomas Soome if ((smap[i].base > addr) && (smap[i].length >= size)) {
938600fd4dSToomas Soome return (smap[i].base);
948600fd4dSToomas Soome }
958600fd4dSToomas Soome }
968600fd4dSToomas Soome return (0);
978600fd4dSToomas Soome }
988600fd4dSToomas Soome
998600fd4dSToomas Soome /*
1008600fd4dSToomas Soome * Find usable address for loading. The address for the kernel is fixed, as
1018600fd4dSToomas Soome * it is determined by kernel linker map (dboot PT_LOAD address).
1028600fd4dSToomas Soome * For modules, we need to consult smap, the module address has to be
1038600fd4dSToomas Soome * aligned to page boundary and we have to fit into smap entry.
1048600fd4dSToomas Soome */
1058600fd4dSToomas Soome vm_offset_t
i386_loadaddr(uint_t type,void * data,vm_offset_t addr)106cb371639SToomas Soome i386_loadaddr(uint_t type, void *data, vm_offset_t addr)
1078600fd4dSToomas Soome {
1088600fd4dSToomas Soome struct stat st;
1098600fd4dSToomas Soome size_t size, smaplen;
1108600fd4dSToomas Soome struct preloaded_file *fp, *mfp;
1118600fd4dSToomas Soome struct file_metadata *md;
1128600fd4dSToomas Soome struct bios_smap *smap;
1138600fd4dSToomas Soome vm_offset_t off;
1148600fd4dSToomas Soome
1158600fd4dSToomas Soome /*
1168600fd4dSToomas Soome * For now, assume we have memory for the kernel, the
1178600fd4dSToomas Soome * required map is [1MB..) This assumption should be safe with x86 BIOS.
1188600fd4dSToomas Soome */
1198600fd4dSToomas Soome if (type == LOAD_KERN)
1208600fd4dSToomas Soome return (addr);
1218600fd4dSToomas Soome
1228600fd4dSToomas Soome if (addr == 0)
1238600fd4dSToomas Soome return (addr); /* nothing to do */
1248600fd4dSToomas Soome
1258600fd4dSToomas Soome if (type == LOAD_ELF)
1268600fd4dSToomas Soome return (0); /* not supported */
1278600fd4dSToomas Soome
1288600fd4dSToomas Soome if (type == LOAD_MEM) {
1298600fd4dSToomas Soome size = *(size_t *)data;
1308600fd4dSToomas Soome } else {
1318600fd4dSToomas Soome stat(data, &st);
1328600fd4dSToomas Soome size = st.st_size;
1338600fd4dSToomas Soome }
1348600fd4dSToomas Soome
1358600fd4dSToomas Soome /*
1368600fd4dSToomas Soome * Find our kernel, from it we will find the smap and the list of
1378600fd4dSToomas Soome * loaded modules.
1388600fd4dSToomas Soome */
1398600fd4dSToomas Soome fp = file_findfile(NULL, NULL);
1408600fd4dSToomas Soome if (fp == NULL)
1418600fd4dSToomas Soome return (0);
1428600fd4dSToomas Soome md = file_findmetadata(fp, MODINFOMD_SMAP);
1438600fd4dSToomas Soome if (md == NULL)
1448600fd4dSToomas Soome return (0);
1458600fd4dSToomas Soome
1468600fd4dSToomas Soome smap = (struct bios_smap *)md->md_data;
147cb371639SToomas Soome smaplen = md->md_size / sizeof (struct bios_smap);
1488600fd4dSToomas Soome
1498600fd4dSToomas Soome /* Start from the end of the kernel. */
1508600fd4dSToomas Soome mfp = fp;
1518600fd4dSToomas Soome do {
1528600fd4dSToomas Soome if (mfp == NULL) {
1538600fd4dSToomas Soome off = roundup2(addr + 1, MULTIBOOT_MOD_ALIGN);
1548600fd4dSToomas Soome } else {
1558600fd4dSToomas Soome off = roundup2(mfp->f_addr + mfp->f_size + 1,
1568600fd4dSToomas Soome MULTIBOOT_MOD_ALIGN);
1578600fd4dSToomas Soome }
158cb371639SToomas Soome /* Avoid possible framebuffer memory */
159cb371639SToomas Soome if (plat_stdout_is_framebuffer()) {
160cb371639SToomas Soome vm_offset_t fb_addr;
161cb371639SToomas Soome size_t fb_size;
162cb371639SToomas Soome
163cb371639SToomas Soome fb_addr = gfx_fb.framebuffer_common.framebuffer_addr;
164cb371639SToomas Soome fb_size = gfx_fb.framebuffer_common.framebuffer_height *
165cb371639SToomas Soome gfx_fb.framebuffer_common.framebuffer_pitch;
166cb371639SToomas Soome
167cb371639SToomas Soome if ((off >= fb_addr && off <= fb_addr + fb_size) ||
168cb371639SToomas Soome (off + size >= fb_addr &&
169cb371639SToomas Soome off + size <= fb_addr + fb_size)) {
170cb371639SToomas Soome printf("\nSkipping framebuffer memory %#x "
171cb371639SToomas Soome "size %#x\n", fb_addr, fb_size);
172cb371639SToomas Soome off = roundup2(fb_addr + fb_size + 1,
173cb371639SToomas Soome MULTIBOOT_MOD_ALIGN);
174cb371639SToomas Soome }
175cb371639SToomas Soome }
1768600fd4dSToomas Soome off = smap_find(smap, smaplen, off, size);
1778600fd4dSToomas Soome off = addr_verify(fp, off, size);
1788600fd4dSToomas Soome if (off != 0)
1798600fd4dSToomas Soome break;
1808600fd4dSToomas Soome
1818600fd4dSToomas Soome if (mfp == NULL)
1828600fd4dSToomas Soome break;
1838600fd4dSToomas Soome mfp = mfp->f_next;
1848600fd4dSToomas Soome } while (off == 0);
1858600fd4dSToomas Soome
1868600fd4dSToomas Soome return (off);
1878600fd4dSToomas Soome }
188199767f8SToomas Soome
189199767f8SToomas Soome ssize_t
i386_copyin(const void * src,vm_offset_t dest,const size_t len)190199767f8SToomas Soome i386_copyin(const void *src, vm_offset_t dest, const size_t len)
191199767f8SToomas Soome {
1928600fd4dSToomas Soome if (dest + len >= memtop) {
1938600fd4dSToomas Soome errno = EFBIG;
1948600fd4dSToomas Soome return (-1);
1958600fd4dSToomas Soome }
196199767f8SToomas Soome
1978600fd4dSToomas Soome bcopy(src, PTOV(dest), len);
1988600fd4dSToomas Soome return (len);
199199767f8SToomas Soome }
200199767f8SToomas Soome
201199767f8SToomas Soome ssize_t
i386_copyout(const vm_offset_t src,void * dest,const size_t len)202199767f8SToomas Soome i386_copyout(const vm_offset_t src, void *dest, const size_t len)
203199767f8SToomas Soome {
2048600fd4dSToomas Soome if (src + len >= memtop) {
2058600fd4dSToomas Soome errno = EFBIG;
2068600fd4dSToomas Soome return (-1);
2078600fd4dSToomas Soome }
2088600fd4dSToomas Soome
2098600fd4dSToomas Soome bcopy(PTOV(src), dest, len);
2108600fd4dSToomas Soome return (len);
211199767f8SToomas Soome }
212199767f8SToomas Soome
213199767f8SToomas Soome
214199767f8SToomas Soome ssize_t
i386_readin(const int fd,vm_offset_t dest,const size_t len)215199767f8SToomas Soome i386_readin(const int fd, vm_offset_t dest, const size_t len)
216199767f8SToomas Soome {
2178600fd4dSToomas Soome if (dest + len >= memtop_copyin) {
2188600fd4dSToomas Soome errno = EFBIG;
2198600fd4dSToomas Soome return (-1);
2208600fd4dSToomas Soome }
221199767f8SToomas Soome
2228600fd4dSToomas Soome return (read(fd, PTOV(dest), len));
223199767f8SToomas Soome }
224