|
@@ -1,94 +1,92 @@
|
1
|
|
-/* Utility functions to hide Etherboot by manipulating the E820 memory
|
2
|
|
- * map. These could go in memsizes.c, but are placed here because not
|
3
|
|
- * all images will need them.
|
|
1
|
+/* Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
|
|
2
|
+ *
|
|
3
|
+ * This program is free software; you can redistribute it and/or
|
|
4
|
+ * modify it under the terms of the GNU General Public License as
|
|
5
|
+ * published by the Free Software Foundation; either version 2 of the
|
|
6
|
+ * License, or any later version.
|
|
7
|
+ *
|
|
8
|
+ * This program is distributed in the hope that it will be useful, but
|
|
9
|
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
11
|
+ * General Public License for more details.
|
|
12
|
+ *
|
|
13
|
+ * You should have received a copy of the GNU General Public License
|
|
14
|
+ * along with this program; if not, write to the Free Software
|
|
15
|
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
4
|
16
|
*/
|
5
|
17
|
|
6
|
|
-#include "etherboot.h"
|
7
|
|
-#include "hidemem.h"
|
|
18
|
+#include <realmode.h>
|
|
19
|
+#include <biosint.h>
|
8
|
20
|
|
9
|
|
-#ifdef CODE16
|
10
|
|
-
|
11
|
|
-static int mangling = 0;
|
12
|
|
-static void *mangler = NULL;
|
13
|
|
-
|
14
|
|
-#define INSTALLED(x) ( (typeof(&x)) ( (void*)(&x) - (void*)e820mangler \
|
15
|
|
- + mangler ) )
|
16
|
|
-#define intercept_int15 INSTALLED(_intercept_int15)
|
17
|
|
-#define intercepted_int15 INSTALLED(_intercepted_int15)
|
18
|
|
-#define hide_memory INSTALLED(_hide_memory)
|
19
|
|
-#define INT15_VECTOR ( (segoff_t*) ( phys_to_virt( 4 * 0x15 ) ) )
|
20
|
|
-
|
21
|
|
-int install_e820mangler ( void *new_mangler ) {
|
22
|
|
- if ( mangling ) return 0;
|
23
|
|
- memcpy ( new_mangler, &e820mangler, e820mangler_size );
|
24
|
|
- mangler = new_mangler;
|
25
|
|
- return 1;
|
26
|
|
-}
|
27
|
|
-
|
28
|
|
-/* Intercept INT15 calls and pass them through the mangler. The
|
29
|
|
- * mangler must have been copied to base memory before making this
|
30
|
|
- * call, and "mangler" must point to the base memory copy, which must
|
31
|
|
- * be 16-byte aligned.
|
|
21
|
+/**
|
|
22
|
+ * A hidden region of Etherboot
|
|
23
|
+ *
|
|
24
|
+ * This represents a region that will be edited out of the system's
|
|
25
|
+ * memory map.
|
|
26
|
+ *
|
|
27
|
+ * This structure is accessed by assembly code, so must not be
|
|
28
|
+ * changed.
|
32
|
29
|
*/
|
33
|
|
-int hide_etherboot ( void ) {
|
34
|
|
- if ( mangling ) return 1;
|
35
|
|
- if ( !mangler ) return 0;
|
|
30
|
+struct hidden_region {
|
|
31
|
+ /* Physical start address */
|
|
32
|
+ uint32_t start;
|
|
33
|
+ /* Physical end address */
|
|
34
|
+ uint32_t end;
|
|
35
|
+};
|
36
|
36
|
|
37
|
|
- /* Hook INT15 handler */
|
38
|
|
- *intercepted_int15 = *INT15_VECTOR;
|
39
|
|
- (*hide_memory)[0].start = virt_to_phys(_text);
|
40
|
|
- (*hide_memory)[0].length = _end - _text;
|
41
|
|
- /* IMPORTANT, possibly even FIXME:
|
42
|
|
- *
|
43
|
|
- * Etherboot has a tendency to claim a very large area of
|
44
|
|
- * memory as possible heap; enough to make it impossible to
|
45
|
|
- * load an OS if we hide all of it. We hide only the portion
|
46
|
|
- * that's currently in use. This means that we MUST NOT
|
47
|
|
- * perform further allocations from the heap while the mangler
|
48
|
|
- * is active.
|
49
|
|
- */
|
50
|
|
- (*hide_memory)[1].start = heap_ptr;
|
51
|
|
- (*hide_memory)[1].length = heap_bot - heap_ptr;
|
52
|
|
- INT15_VECTOR->segment = SEGMENT(mangler);
|
53
|
|
- INT15_VECTOR->offset = 0;
|
|
37
|
+/* Linker-defined symbols */
|
|
38
|
+extern char _text[];
|
|
39
|
+extern char _end[];
|
54
|
40
|
|
55
|
|
- mangling = 1;
|
56
|
|
- return 1;
|
57
|
|
-}
|
|
41
|
+/** Assembly routine in e820mangler.S */
|
|
42
|
+extern void int15();
|
58
|
43
|
|
59
|
|
-int unhide_etherboot ( void ) {
|
60
|
|
- if ( !mangling ) return 1;
|
|
44
|
+/** Vector for storing original INT 15 handler */
|
|
45
|
+extern struct segoff __text16 ( int15_vector );
|
|
46
|
+#define int15_vector __use_text16 ( int15_vector )
|
61
|
47
|
|
62
|
|
- /* Restore original INT15 handler
|
63
|
|
- */
|
64
|
|
- if ( VIRTUAL(INT15_VECTOR->segment,INT15_VECTOR->offset) != mangler ) {
|
65
|
|
- /* Oh dear... */
|
|
48
|
+/**
|
|
49
|
+ * Unique IDs for hidden regions
|
|
50
|
+ */
|
|
51
|
+enum {
|
|
52
|
+ TEXT = 0,
|
|
53
|
+};
|
66
|
54
|
|
67
|
|
-#ifdef WORK_AROUND_BPBATCH_BUG
|
68
|
|
- /* BpBatch intercepts INT15, so can't unhook it, and
|
69
|
|
- * then proceeds to ignore our PXENV_KEEP_UNDI return
|
70
|
|
- * status, which means that it ends up zeroing out the
|
71
|
|
- * INT15 handler routine.
|
72
|
|
- *
|
73
|
|
- * This rather ugly hack involves poking into
|
74
|
|
- * BpBatch's code and changing it's stored value for
|
75
|
|
- * the "next handler" in the INT15 chain.
|
76
|
|
- */
|
77
|
|
- segoff_t *bp_chain = VIRTUAL ( 0x0060, 0x8254 );
|
|
55
|
+/**
|
|
56
|
+ * List of hidden regions
|
|
57
|
+ *
|
|
58
|
+ * Must be terminated by a zero entry.
|
|
59
|
+ */
|
|
60
|
+struct hidden_region __data16_array ( hidden_regions, [] ) = {
|
|
61
|
+ [TEXT] = { 0, 0 },
|
|
62
|
+ { 0, 0, } /* Terminator */
|
|
63
|
+};
|
|
64
|
+#define hidden_regions __use_data16 ( hidden_regions )
|
78
|
65
|
|
79
|
|
- if ( ( bp_chain->segment == SEGMENT(mangler) ) &&
|
80
|
|
- ( bp_chain->offset == 0 ) ) {
|
81
|
|
- printf ( "\nBPBATCH bug workaround enabled\n" );
|
82
|
|
- *bp_chain = *intercepted_int15;
|
83
|
|
- }
|
84
|
|
-#endif /* WORK_AROUND_BPBATCH_BUG */
|
|
66
|
+/**
|
|
67
|
+ * Hide Etherboot
|
|
68
|
+ *
|
|
69
|
+ * Installs an INT 15 handler to edit Etherboot out of the memory map
|
|
70
|
+ * returned by the BIOS.
|
|
71
|
+ */
|
|
72
|
+void hide_etherboot ( void ) {
|
|
73
|
+ hidden_regions[TEXT].start = virt_to_phys ( _text );
|
|
74
|
+ hidden_regions[TEXT].end = virt_to_phys ( _end );
|
85
|
75
|
|
86
|
|
- return 0;
|
87
|
|
- }
|
88
|
|
- *INT15_VECTOR = *intercepted_int15;
|
|
76
|
+ DBG ( "Hiding [%x,%x)\n", hidden_regions[TEXT].start,
|
|
77
|
+ hidden_regions[TEXT].end );
|
89
|
78
|
|
90
|
|
- mangling = 0;
|
91
|
|
- return 1;
|
|
79
|
+ hook_bios_interrupt ( 0x15, ( unsigned int ) int15,
|
|
80
|
+ &int15_vector );
|
92
|
81
|
}
|
93
|
82
|
|
94
|
|
-#endif /* CODE16 */
|
|
83
|
+/**
|
|
84
|
+ * Unhide Etherboot
|
|
85
|
+ *
|
|
86
|
+ * Uninstalls the INT 15 handler installed by hide_etherboot(), if
|
|
87
|
+ * possible.
|
|
88
|
+ */
|
|
89
|
+void unhide_etherboot ( void ) {
|
|
90
|
+ unhook_bios_interrupt ( 0x15, ( unsigned int ) int15,
|
|
91
|
+ &int15_vector );
|
|
92
|
+}
|