Bladeren bron

Code to install the new E820 mangler (which doesn't require copying

down to base memory, since it is now in the base-memory-resident
.text16 section).
tags/v0.9.3
Michael Brown 18 jaren geleden
bovenliggende
commit
5e80847827
1 gewijzigde bestanden met toevoegingen van 78 en 80 verwijderingen
  1. 78
    80
      src/arch/i386/firmware/pcbios/hidemem.c

+ 78
- 80
src/arch/i386/firmware/pcbios/hidemem.c Bestand weergeven

@@ -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
+}

Laden…
Annuleren
Opslaan