xref: /openbsd/sys/arch/amd64/stand/efiboot/memprobe.c (revision 55cc5ba3)
1 /*	$OpenBSD: memprobe.c,v 1.2 2021/01/28 18:54:50 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 1997-1999 Michael Shalayeff
5  * Copyright (c) 1997-1999 Tobias Weingartner
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30 
31 #include <sys/param.h>
32 #include <machine/biosvar.h>
33 #include <dev/isa/isareg.h>
34 #include <stand/boot/bootarg.h>
35 #include "libsa.h"
36 
37 u_int cnvmem, extmem;		/* XXX - compatibility */
38 
39 extern bios_memmap_t bios_memmap[64];	/* This is easier */
40 
41 void
42 dump_biosmem(bios_memmap_t *tm)
43 {
44 	register bios_memmap_t *p;
45 	register u_int total = 0;
46 
47 	if (tm == NULL)
48 		tm = bios_memmap;
49 
50 	for (p = tm; p->type != BIOS_MAP_END; p++) {
51 		printf("Region %ld: type %u at 0x%llx for %uKB\n",
52 		    (long)(p - tm), p->type, p->addr,
53 		    (u_int)(p->size / 1024));
54 
55 		if (p->type == BIOS_MAP_FREE)
56 			total += p->size / 1024;
57 	}
58 
59 	printf("Low ram: %dKB  High ram: %dKB\n", cnvmem, extmem);
60 	printf("Total free memory: %uKB\n", total);
61 }
62 
63 int
64 mem_limit(long long ml)
65 {
66 	register bios_memmap_t *p;
67 
68 	for (p = bios_memmap; p->type != BIOS_MAP_END; p++) {
69 		register int64_t sp = p->addr, ep = p->addr + p->size;
70 
71 		if (p->type != BIOS_MAP_FREE)
72 			continue;
73 
74 		/* Wholly above limit, nuke it */
75 		if ((sp >= ml) && (ep >= ml)) {
76 			bcopy (p + 1, p, (char *)bios_memmap +
77 			       sizeof(bios_memmap) - (char *)p);
78 		} else if ((sp < ml) && (ep >= ml)) {
79 			p->size -= (ep - ml);
80 		}
81 	}
82 	return 0;
83 }
84 
85 int
86 mem_delete(long long sa, long long ea)
87 {
88 	register bios_memmap_t *p;
89 
90 	for (p = bios_memmap; p->type != BIOS_MAP_END; p++) {
91 		if (p->type == BIOS_MAP_FREE) {
92 			register int64_t sp = p->addr, ep = p->addr + p->size;
93 
94 			/* can we eat it as a whole? */
95 			if ((sa - sp) <= PAGE_SIZE && (ep - ea) <= PAGE_SIZE) {
96 				bcopy(p + 1, p, (char *)bios_memmap +
97 				    sizeof(bios_memmap) - (char *)p);
98 				break;
99 			/* eat head or legs */
100 			} else if (sa <= sp && sp < ea) {
101 				p->addr = ea;
102 				p->size = ep - ea;
103 				break;
104 			} else if (sa < ep && ep <= ea) {
105 				p->size = sa - sp;
106 				break;
107 			} else if (sp < sa && ea < ep) {
108 				/* bite in half */
109 				bcopy(p, p + 1, (char *)bios_memmap +
110 				    sizeof(bios_memmap) - (char *)p -
111 				    sizeof(bios_memmap[0]));
112 				p[1].addr = ea;
113 				p[1].size = ep - ea;
114 				p->size = sa - sp;
115 				break;
116 			}
117 		}
118 	}
119 	return 0;
120 }
121 
122 int
123 mem_add(long long sa, long long ea)
124 {
125 	register bios_memmap_t *p;
126 
127 	for (p = bios_memmap; p->type != BIOS_MAP_END; p++) {
128 		if (p->type == BIOS_MAP_FREE) {
129 			register int64_t sp = p->addr, ep = p->addr + p->size;
130 
131 			/* is it already there? */
132 			if (sp <= sa && ea <= ep) {
133 				break;
134 			/* join head or legs */
135 			} else if (sa < sp && sp <= ea) {
136 				p->addr = sa;
137 				p->size = ep - sa;
138 				break;
139 			} else if (sa <= ep && ep < ea) {
140 				p->size = ea - sp;
141 				break;
142 			} else if (ea < sp) {
143 				/* insert before */
144 				bcopy(p, p + 1, (char *)bios_memmap +
145 				    sizeof(bios_memmap) - (char *)(p - 1));
146 				p->addr = sa;
147 				p->size = ea - sa;
148 				break;
149 			}
150 		}
151 	}
152 
153 	/* meaning add new item at the end of the list */
154 	if (p->type == BIOS_MAP_END) {
155 		p[1] = p[0];
156 		p->type = BIOS_MAP_FREE;
157 		p->addr = sa;
158 		p->size = ea - sa;
159 	}
160 
161 	return 0;
162 }
163 
164 void
165 mem_pass(void)
166 {
167 	bios_memmap_t *p;
168 
169 	for (p = bios_memmap; p->type != BIOS_MAP_END; p++)
170 		;
171 	addbootarg(BOOTARG_MEMMAP, (p - bios_memmap + 1) * sizeof *bios_memmap,
172 	    bios_memmap);
173 }
174