|
@@ -42,6 +42,13 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
42
|
42
|
|
43
|
43
|
struct image_type com32_image_type __image_type ( PROBE_NORMAL );
|
44
|
44
|
|
|
45
|
+struct idt_register com32_external_idtr = {
|
|
46
|
+ .limit = COM32_NUM_IDT_ENTRIES * sizeof ( struct idt_descriptor ) - 1,
|
|
47
|
+ .base = COM32_IDT
|
|
48
|
+};
|
|
49
|
+
|
|
50
|
+struct idt_register com32_internal_idtr;
|
|
51
|
+
|
45
|
52
|
/**
|
46
|
53
|
* Execute COMBOOT image
|
47
|
54
|
*
|
|
@@ -89,9 +96,12 @@ static int com32_exec ( struct image *image ) {
|
89
|
96
|
unregister_image ( image );
|
90
|
97
|
|
91
|
98
|
__asm__ __volatile__ (
|
|
99
|
+ "sidt com32_internal_idtr\n\t"
|
|
100
|
+ "lidt com32_external_idtr\n\t" /* Set up IDT */
|
92
|
101
|
"movl %%esp, (com32_internal_esp)\n\t" /* Save internal virtual address space ESP */
|
93
|
102
|
"movl (com32_external_esp), %%esp\n\t" /* Switch to COM32 ESP (top of available memory) */
|
94
|
103
|
"call _virt_to_phys\n\t" /* Switch to flat physical address space */
|
|
104
|
+ "sti\n\t" /* Enable interrupts */
|
95
|
105
|
"pushl %0\n\t" /* Pointer to CDECL helper function */
|
96
|
106
|
"pushl %1\n\t" /* Pointer to FAR call helper function */
|
97
|
107
|
"pushl %2\n\t" /* Size of low memory bounce buffer */
|
|
@@ -100,7 +110,9 @@ static int com32_exec ( struct image *image ) {
|
100
|
110
|
"pushl %5\n\t" /* Pointer to the command line arguments */
|
101
|
111
|
"pushl $6\n\t" /* Number of additional arguments */
|
102
|
112
|
"call *%6\n\t" /* Execute image */
|
103
|
|
- "call _phys_to_virt\n\t" /* Switch back to internal virtual address space */
|
|
113
|
+ "cli\n\t" /* Disable interrupts */
|
|
114
|
+ "call _phys_to_virt\n\t" /* Switch back to internal virtual address space */
|
|
115
|
+ "lidt com32_internal_idtr\n\t" /* Switch back to internal IDT (for debugging) */
|
104
|
116
|
"movl (com32_internal_esp), %%esp\n\t" /* Switch back to internal stack */
|
105
|
117
|
:
|
106
|
118
|
:
|
|
@@ -191,25 +203,55 @@ static int com32_identify ( struct image *image ) {
|
191
|
203
|
|
192
|
204
|
|
193
|
205
|
/**
|
194
|
|
- * Load COM32 image into memory
|
|
206
|
+ * Load COM32 image into memory and set up the IDT
|
195
|
207
|
* @v image COM32 image
|
196
|
208
|
* @ret rc Return status code
|
197
|
209
|
*/
|
198
|
210
|
static int comboot_load_image ( struct image *image ) {
|
|
211
|
+ physaddr_t com32_irq_wrapper_phys;
|
|
212
|
+ struct idt_descriptor *idt;
|
|
213
|
+ struct ijb_entry *ijb;
|
199
|
214
|
size_t filesz, memsz;
|
200
|
215
|
userptr_t buffer;
|
201
|
|
- int rc;
|
202
|
|
-
|
203
|
|
- filesz = image->len;
|
|
216
|
+ int rc, i;
|
|
217
|
+
|
|
218
|
+ /* The interrupt descriptor table, interrupt jump buffer, and
|
|
219
|
+ * image data are all contiguous in memory. Prepare them all at once.
|
|
220
|
+ */
|
|
221
|
+ filesz = image->len +
|
|
222
|
+ COM32_NUM_IDT_ENTRIES * sizeof ( struct idt_descriptor ) +
|
|
223
|
+ COM32_NUM_IDT_ENTRIES * sizeof ( struct ijb_entry );
|
204
|
224
|
memsz = filesz;
|
205
|
|
- buffer = phys_to_user ( COM32_START_PHYS );
|
|
225
|
+ buffer = phys_to_user ( COM32_IDT );
|
206
|
226
|
if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
|
207
|
227
|
DBGC ( image, "COM32 %p: could not prepare segment: %s\n",
|
208
|
228
|
image, strerror ( rc ) );
|
209
|
229
|
return rc;
|
210
|
230
|
}
|
211
|
231
|
|
|
232
|
+ /* Write the IDT and IJB */
|
|
233
|
+ idt = phys_to_virt ( COM32_IDT );
|
|
234
|
+ ijb = phys_to_virt ( COM32_IJB );
|
|
235
|
+ com32_irq_wrapper_phys = virt_to_phys ( com32_irq_wrapper );
|
|
236
|
+
|
|
237
|
+ for ( i = 0; i < COM32_NUM_IDT_ENTRIES; i++ ) {
|
|
238
|
+ uint32_t ijb_address = virt_to_phys ( &ijb[i] );
|
|
239
|
+
|
|
240
|
+ idt[i].offset_low = ijb_address & 0xFFFF;
|
|
241
|
+ idt[i].selector = PHYSICAL_CS;
|
|
242
|
+ idt[i].flags = IDT_INTERRUPT_GATE_FLAGS;
|
|
243
|
+ idt[i].offset_high = ijb_address >> 16;
|
|
244
|
+
|
|
245
|
+ ijb[i].pusha_instruction = IJB_PUSHA;
|
|
246
|
+ ijb[i].mov_instruction = IJB_MOV_AL_IMM8;
|
|
247
|
+ ijb[i].mov_value = i;
|
|
248
|
+ ijb[i].jump_instruction = IJB_JMP_REL32;
|
|
249
|
+ ijb[i].jump_destination = com32_irq_wrapper_phys -
|
|
250
|
+ virt_to_phys ( &ijb[i + 1] );
|
|
251
|
+ }
|
|
252
|
+
|
212
|
253
|
/* Copy image to segment */
|
|
254
|
+ buffer = phys_to_user ( COM32_START_PHYS );
|
213
|
255
|
memcpy_user ( buffer, 0, image->data, 0, filesz );
|
214
|
256
|
|
215
|
257
|
return 0;
|