2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
30 * MD primitives supporting placement of module data
32 * XXX should check load address/size against memory top.
35 #include <sys/param.h>
36 #include <sys/multiboot2.h>
37 #include <machine/metadata.h>
38 #include <machine/pc/bios.h>
41 #include "bootstrap.h"
44 * Verify the address is not in use by existing modules.
47 addr_verify(struct preloaded_file
*fp
, vm_offset_t addr
, size_t size
)
54 if ((f_addr
<= addr
) &&
55 (f_addr
+ fp
->f_size
>= addr
)) {
58 if ((f_addr
>= addr
) && (f_addr
<= addr
+ size
)) {
67 * Find smap entry above 1MB, able to contain size bytes from addr.
70 smap_find(struct bios_smap
*smap
, int smaplen
, vm_offset_t addr
, size_t size
)
74 for (i
= 0; i
< smaplen
; i
++) {
75 if (smap
[i
].type
!= SMAP_TYPE_MEMORY
)
78 /* We do not want address below 1MB. */
79 if (smap
[i
].base
< 0x100000)
82 /* Do we fit into current entry? */
83 if ((smap
[i
].base
<= addr
) &&
84 (smap
[i
].base
+ smap
[i
].length
>= addr
+ size
)) {
88 /* Do we fit into new entry? */
89 if ((smap
[i
].base
> addr
) && (smap
[i
].length
>= size
)) {
90 return (smap
[i
].base
);
97 * Find usable address for loading. The address for the kernel is fixed, as
98 * it is determined by kernel linker map (dboot PT_LOAD address).
99 * For modules, we need to consult smap, the module address has to be
100 * aligned to page boundary and we have to fit into smap entry.
103 i386_loadaddr(u_int type
, void *data
, vm_offset_t addr
)
106 size_t size
, smaplen
;
107 struct preloaded_file
*fp
, *mfp
;
108 struct file_metadata
*md
;
109 struct bios_smap
*smap
;
113 * For now, assume we have memory for the kernel, the
114 * required map is [1MB..) This assumption should be safe with x86 BIOS.
116 if (type
== LOAD_KERN
)
120 return (addr
); /* nothing to do */
122 if (type
== LOAD_ELF
)
123 return (0); /* not supported */
125 if (type
== LOAD_MEM
) {
126 size
= *(size_t *)data
;
133 * Find our kernel, from it we will find the smap and the list of
136 fp
= file_findfile(NULL
, NULL
);
139 md
= file_findmetadata(fp
, MODINFOMD_SMAP
);
143 smap
= (struct bios_smap
*)md
->md_data
;
144 smaplen
= md
->md_size
/ sizeof(struct bios_smap
);
146 /* Start from the end of the kernel. */
150 off
= roundup2(addr
+ 1, MULTIBOOT_MOD_ALIGN
);
152 off
= roundup2(mfp
->f_addr
+ mfp
->f_size
+ 1,
153 MULTIBOOT_MOD_ALIGN
);
155 off
= smap_find(smap
, smaplen
, off
, size
);
156 off
= addr_verify(fp
, off
, size
);
169 i386_copyin(const void *src
, vm_offset_t dest
, const size_t len
)
171 if (dest
+ len
>= memtop
) {
176 bcopy(src
, PTOV(dest
), len
);
181 i386_copyout(const vm_offset_t src
, void *dest
, const size_t len
)
183 if (src
+ len
>= memtop
) {
188 bcopy(PTOV(src
), dest
, len
);
194 i386_readin(const int fd
, vm_offset_t dest
, const size_t len
)
196 if (dest
+ len
>= memtop_copyin
) {
201 return (read(fd
, PTOV(dest
), len
));