2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 .section ".text16", "ax", @progbits
22 .section ".data16", "aw", @progbits
23 .section ".text16.data", "aw", @progbits
26 #define SMAP 0x534d4150
28 /****************************************************************************
32 * %edx:%eax Region start
33 * %ecx:%ebx Region end
34 * %si Pointer to hidden region descriptor
36 * CF set Region overlaps
38 ****************************************************************************
42 /* If start >= hidden_end, there is no overlap. */
47 /* If end <= hidden_start, there is no overlap; equivalently,
48 * if end > hidden_start, there is overlap.
60 .size check_overlap, . - check_overlap
62 /****************************************************************************
63 * Check for overflow/underflow
66 * %edx:%eax Region start
67 * %ecx:%ebx Region end
70 * CF clear start >= end
71 ****************************************************************************
82 .size check_overflow, . - check_overflow
84 /****************************************************************************
85 * Truncate towards start of region
88 * %edx:%eax Region start
89 * %ecx:%ebx Region end
90 * %si Pointer to hidden region descriptor
92 * %edx:%eax Modified region start
93 * %ecx:%ebx Modified region end
94 * CF set Region was truncated
95 * CF clear Region was not truncated
96 ****************************************************************************
100 /* If overlaps, set region end = hidden region start */
105 /* If region end < region start, set region end = region start */
112 .size truncate_to_start, . - truncate_to_start
114 /****************************************************************************
115 * Truncate towards end of region
118 * %edx:%eax Region start
119 * %ecx:%ebx Region end
120 * %si Pointer to hidden region descriptor
122 * %edx:%eax Modified region start
123 * %ecx:%ebx Modified region end
124 * CF set Region was truncated
125 * CF clear Region was not truncated
126 ****************************************************************************
130 /* If overlaps, set region start = hidden region end */
135 /* If region start > region end, set region start = region end */
142 .size truncate_to_end, . - truncate_to_end
144 /****************************************************************************
148 * %edx:%eax Region start
149 * %ecx:%ebx Region length (*not* region end)
150 * %bp truncate_to_start or truncate_to_end
152 * %edx:%eax Modified region start
153 * %ecx:%ebx Modified region length
154 * CF set Region was truncated
155 * CF clear Region was not truncated
156 ****************************************************************************
162 /* Convert (start,len) to (start,end) */
165 /* Hide all hidden regions, truncating as directed */
166 movw $hidden_regions, %si
169 popfw /* If CF was set, set stored CF in flags word on stack */
175 /* Convert modified (start,end) back to (start,len) */
181 .size truncate, . - truncate
183 /****************************************************************************
184 * Patch "memory above 1MB" figure
187 * %ax Memory above 1MB, in 1kB blocks
189 * %ax Modified memory above 1M in 1kB blocks
190 * CF set Region was truncated
191 * CF clear Region was not truncated
192 ****************************************************************************
197 /* Convert to (start,len) format and call truncate */
198 movw $truncate_to_start, %bp
205 /* Convert back to "memory above 1MB" format and return via %ax */
213 .size patch_1m, . - patch_1m
215 /****************************************************************************
216 * Patch "memory above 16MB" figure
219 * %bx Memory above 16MB, in 64kB blocks
221 * %bx Modified memory above 16M in 64kB blocks
222 * CF set Region was truncated
223 * CF clear Region was not truncated
224 ****************************************************************************
229 /* Convert to (start,len) format and call truncate */
230 movw $truncate_to_start, %bp
234 movl $0x1000000, %eax
236 /* Convert back to "memory above 16MB" format and return via %bx */
244 .size patch_16m, . - patch_16m
246 /****************************************************************************
247 * Patch "memory between 1MB and 16MB" and "memory above 16MB" figures
250 * %ax Memory between 1MB and 16MB, in 1kB blocks
251 * %bx Memory above 16MB, in 64kB blocks
253 * %ax Modified memory between 1MB and 16MB, in 1kB blocks
254 * %bx Modified memory above 16MB, in 64kB blocks
255 * CF set Region was truncated
256 * CF clear Region was not truncated
257 ****************************************************************************
265 1: /* 1m region was truncated; kill the 16m region */
268 .size patch_1m_16m, . - patch_1m_16m
270 /****************************************************************************
271 * Patch E820 memory map entry
274 * %es:di Pointer to E820 memory map descriptor
275 * %bp truncate_to_start or truncate_to_end
277 * %es:di Pointer to now-modified E820 memory map descriptor
278 * CF set Region was truncated
279 * CF clear Region was not truncated
280 ****************************************************************************
285 movl %es:0(%di), %eax
286 movl %es:4(%di), %edx
287 movl %es:8(%di), %ebx
288 movl %es:12(%di), %ecx
290 movl %eax, %es:0(%di)
291 movl %edx, %es:4(%di)
292 movl %ebx, %es:8(%di)
293 movl %ecx, %es:12(%di)
296 .size patch_e820, . - patch_e820
298 /****************************************************************************
299 * Split E820 memory map entry if necessary
306 * Calls the underlying INT 15,e820 and returns a modified memory map.
307 * Regions will be split around any hidden regions.
308 ****************************************************************************
314 /* Caller's %bx => %si, real %ebx to %ebx, call previous handler */
319 movl %ebx, %cs:real_ebx
320 1: movl %cs:real_ebx, %ebx
321 lcall *%cs:int15_vector
327 movw $truncate_to_start, %bp
330 movw $truncate_to_end, %bp
336 movl %ebx, %cs:real_ebx
341 /* Restore flags returned by previous handler and return */
346 .size split_e820, . - split_e820
348 .section ".text16.data"
351 .size real_ebx, . - real_ebx
353 /****************************************************************************
354 * INT 15,e820 handler
355 ****************************************************************************
364 /* If we've hit an error, exit immediately */
366 /* If region is non-empty, return this region */
368 movl %es:8(%di), %eax
369 orl %es:12(%di), %eax
372 /* Region is empty. If this is not the end of the map,
373 * skip over this region.
382 1: /* Region is empty and this is the end of the map. Return
383 * with CF set to avoid placing an empty region at the end of
389 99: /* Restore flags from original INT 15,e820 call and return */
391 addr32 leal 12(%esp), %esp /* avoid changing flags */
393 .size int15_e820, . - int15_e820
395 /****************************************************************************
396 * INT 15,e801 handler
397 ****************************************************************************
401 /* Call previous handler */
403 lcall *%cs:int15_vector
416 /* Restore flags returned by previous handler and return */
419 .size int15_e801, . - int15_e801
421 /****************************************************************************
423 ****************************************************************************
427 /* Call previous handler */
429 lcall *%cs:int15_vector
437 /* Restore flags returned by previous handler and return */
440 .size int15_88, . - int15_88
442 /****************************************************************************
444 ****************************************************************************
449 /* See if we want to intercept this call */
466 ljmp *%cs:int15_vector
467 .size int15, . - int15
469 .section ".text16.data"
473 .size int15_vector, . - int15_vector