|
@@ -35,6 +35,20 @@
|
35
|
35
|
|
36
|
36
|
struct image_type bzimage_image_type __image_type ( PROBE_NORMAL );
|
37
|
37
|
|
|
38
|
+/**
|
|
39
|
+ * bzImage execution context
|
|
40
|
+ */
|
|
41
|
+union bzimage_exec_context {
|
|
42
|
+ /** Real-mode parameters */
|
|
43
|
+ struct {
|
|
44
|
+ /** Kernel real-mode data segment */
|
|
45
|
+ uint16_t kernel_seg;
|
|
46
|
+ /** Kernel real-mode stack pointer */
|
|
47
|
+ uint16_t stack;
|
|
48
|
+ } rm;
|
|
49
|
+ unsigned long ul;
|
|
50
|
+};
|
|
51
|
+
|
38
|
52
|
/**
|
39
|
53
|
* Execute bzImage image
|
40
|
54
|
*
|
|
@@ -42,7 +56,10 @@ struct image_type bzimage_image_type __image_type ( PROBE_NORMAL );
|
42
|
56
|
* @ret rc Return status code
|
43
|
57
|
*/
|
44
|
58
|
static int bzimage_exec ( struct image *image ) {
|
45
|
|
- unsigned long rm_kernel_seg = image->priv.ul;
|
|
59
|
+ union bzimage_exec_context context;
|
|
60
|
+
|
|
61
|
+ /* Retrieve stored execution context */
|
|
62
|
+ context.ul = image->priv.ul;
|
46
|
63
|
|
47
|
64
|
/* Prepare for exiting */
|
48
|
65
|
shutdown();
|
|
@@ -57,13 +74,14 @@ static int bzimage_exec ( struct image *image ) {
|
57
|
74
|
"pushw %w2\n\t"
|
58
|
75
|
"pushw $0\n\t"
|
59
|
76
|
"lret\n\t" )
|
60
|
|
- : : "r" ( rm_kernel_seg ),
|
61
|
|
- "i" ( BZI_STACK_SIZE ),
|
62
|
|
- "r" ( rm_kernel_seg + 0x20 ) );
|
|
77
|
+ : : "r" ( context.rm.kernel_seg ),
|
|
78
|
+ "r" ( context.rm.stack ),
|
|
79
|
+ "r" ( context.rm.kernel_seg + 0x20 ) );
|
63
|
80
|
|
64
|
81
|
/* There is no way for the image to return, since we provide
|
65
|
82
|
* no return address.
|
66
|
83
|
*/
|
|
84
|
+ assert ( 0 );
|
67
|
85
|
|
68
|
86
|
return -ECANCELED; /* -EIMPOSSIBLE */
|
69
|
87
|
}
|
|
@@ -76,7 +94,8 @@ static int bzimage_exec ( struct image *image ) {
|
76
|
94
|
*/
|
77
|
95
|
int bzimage_load ( struct image *image ) {
|
78
|
96
|
struct bzimage_header bzhdr;
|
79
|
|
- unsigned int rm_kernel_seg = 0x7c0; /* place RM kernel at 07c0:0000 */
|
|
97
|
+ union bzimage_exec_context context;
|
|
98
|
+ unsigned int rm_kernel_seg = 0x1000; /* place RM kernel at 1000:0000 */
|
80
|
99
|
userptr_t rm_kernel = real_to_user ( rm_kernel_seg, 0 );
|
81
|
100
|
userptr_t pm_kernel;
|
82
|
101
|
size_t rm_filesz;
|
|
@@ -115,7 +134,7 @@ int bzimage_load ( struct image *image ) {
|
115
|
134
|
DBGC ( image, "bzImage %p version %04x\n", image, bzhdr.version );
|
116
|
135
|
|
117
|
136
|
/* Check size of base memory portions */
|
118
|
|
- rm_filesz = ( ( bzhdr.setup_sects ? bzhdr.setup_sects : 4 ) << 9 );
|
|
137
|
+ rm_filesz = ( ( bzhdr.setup_sects ? bzhdr.setup_sects : 4 ) + 1 ) << 9;
|
119
|
138
|
if ( rm_filesz > image->len ) {
|
120
|
139
|
DBGC ( image, "bzImage %p too short for %zd byte of setup\n",
|
121
|
140
|
image, rm_filesz );
|
|
@@ -177,8 +196,10 @@ int bzimage_load ( struct image *image ) {
|
177
|
196
|
}
|
178
|
197
|
copy_to_user ( rm_kernel, BZI_HDR_OFFSET, &bzhdr, sizeof ( bzhdr ) );
|
179
|
198
|
|
180
|
|
- /* Record segment address in image private data field */
|
181
|
|
- image->priv.ul = rm_kernel_seg;
|
|
199
|
+ /* Record execution context in image private data field */
|
|
200
|
+ context.rm.kernel_seg = rm_kernel_seg;
|
|
201
|
+ context.rm.stack = rm_heap_end;
|
|
202
|
+ image->priv.ul = context.ul;
|
182
|
203
|
|
183
|
204
|
return 0;
|
184
|
205
|
}
|