Browse Source

[comboot] Support COMBOOT in 64-bit builds

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 8 years ago
parent
commit
5e5450c2d0

+ 0
- 2
src/arch/i386/Makefile View File

@@ -83,9 +83,7 @@ endif
83 83
 # i386-specific directories containing source files
84 84
 #
85 85
 SRCDIRS		+= arch/i386/core
86
-SRCDIRS		+= arch/i386/image
87 86
 SRCDIRS		+= arch/i386/tests
88
-SRCDIRS		+= arch/i386/interface/syslinux
89 87
 
90 88
 # Include common x86 Makefile
91 89
 #

+ 1
- 0
src/arch/x86/Makefile View File

@@ -16,6 +16,7 @@ SRCDIRS		+= arch/x86/interface/pxe
16 16
 SRCDIRS		+= arch/x86/interface/pxeparent
17 17
 SRCDIRS		+= arch/x86/interface/efi
18 18
 SRCDIRS		+= arch/x86/interface/vmware
19
+SRCDIRS		+= arch/x86/interface/syslinux
19 20
 SRCDIRS		+= arch/x86/prefix
20 21
 SRCDIRS		+= arch/x86/hci/commands
21 22
 SRCDIRS		+= arch/x86/drivers/xen

src/arch/i386/image/com32.c → src/arch/x86/image/com32.c View File

@@ -76,8 +76,6 @@ static int com32_exec_loop ( struct image *image ) {
76 76
 
77 77
 		assert ( avail_mem_top != 0 );
78 78
 
79
-		com32_external_esp = phys_to_virt ( avail_mem_top );
80
-
81 79
 		/* Hook COMBOOT API interrupts */
82 80
 		hook_comboot_interrupts();
83 81
 
@@ -88,34 +86,44 @@ static int com32_exec_loop ( struct image *image ) {
88 86
 		 */
89 87
 		unregister_image ( image );
90 88
 
91
-		__asm__ __volatile__ (
92
-			"movl %%esp, (com32_internal_esp)\n\t" /* Save internal virtual address space ESP */
93
-			"movl (com32_external_esp), %%esp\n\t" /* Switch to COM32 ESP (top of available memory) */
94
-			"call _virt_to_phys\n\t"               /* Switch to flat physical address space */
95
-			"sti\n\t"			       /* Enable interrupts */
96
-			"pushl %0\n\t"                         /* Pointer to CDECL helper function */
97
-			"pushl %1\n\t"                         /* Pointer to FAR call helper function */
98
-			"pushl %2\n\t"                         /* Size of low memory bounce buffer */
99
-			"pushl %3\n\t"                         /* Pointer to low memory bounce buffer */
100
-			"pushl %4\n\t"                         /* Pointer to INT call helper function */
101
-			"pushl %5\n\t"                         /* Pointer to the command line arguments */
102
-			"pushl $6\n\t"                         /* Number of additional arguments */
103
-			"call *%6\n\t"                         /* Execute image */
104
-			"cli\n\t"			       /* Disable interrupts */
105
-			"call _phys_to_virt\n\t"               /* Switch back to internal virtual address space */
106
-			"movl (com32_internal_esp), %%esp\n\t" /* Switch back to internal stack */
107
-		:
108
-		:
109
-			/* %0 */ "r" ( virt_to_phys ( com32_cfarcall_wrapper ) ),
110
-			/* %1 */ "r" ( virt_to_phys ( com32_farcall_wrapper ) ),
111
-			/* %2 */ "r" ( get_fbms() * 1024 - (COM32_BOUNCE_SEG << 4) ),
112
-			/* %3 */ "i" ( COM32_BOUNCE_SEG << 4 ),
113
-			/* %4 */ "r" ( virt_to_phys ( com32_intcall_wrapper ) ),
114
-			/* %5 */ "r" ( virt_to_phys ( image->cmdline ?
115
-						      image->cmdline : "" ) ),
116
-			/* %6 */ "r" ( COM32_START_PHYS )
117
-		:
118
-			"memory" );
89
+		__asm__ __volatile__ ( PHYS_CODE (
90
+			/* Preserve registers */
91
+			"pushal\n\t"
92
+			/* Preserve stack pointer */
93
+			"subl $4, %k0\n\t"
94
+			"movl %%esp, (%k0)\n\t"
95
+			/* Switch to COM32 stack */
96
+			"movl %k0, %%esp\n\t"
97
+			/* Enable interrupts */
98
+			"sti\n\t"
99
+			/* Construct stack frame */
100
+			"pushl %k1\n\t"
101
+			"pushl %k2\n\t"
102
+			"pushl %k3\n\t"
103
+			"pushl %k4\n\t"
104
+			"pushl %k5\n\t"
105
+			"pushl %k6\n\t"
106
+			"pushl $6\n\t"
107
+			/* Call COM32 entry point */
108
+			"movl %k7, %k0\n\t"
109
+			"call *%k0\n\t"
110
+			/* Disable interrupts */
111
+			"cli\n\t"
112
+			/* Restore stack pointer */
113
+			"movl 24(%%esp), %%esp\n\t"
114
+			/* Restore registers */
115
+			"popal\n\t" )
116
+			:
117
+			: "r" ( avail_mem_top ),
118
+			  "r" ( virt_to_phys ( com32_cfarcall_wrapper ) ),
119
+			  "r" ( virt_to_phys ( com32_farcall_wrapper ) ),
120
+			  "r" ( get_fbms() * 1024 - ( COM32_BOUNCE_SEG << 4 ) ),
121
+			  "i" ( COM32_BOUNCE_SEG << 4 ),
122
+			  "r" ( virt_to_phys ( com32_intcall_wrapper ) ),
123
+			  "r" ( virt_to_phys ( image->cmdline ?
124
+					       image->cmdline : "" ) ),
125
+			  "i" ( COM32_START_PHYS )
126
+			: "memory" );
119 127
 		DBGC ( image, "COM32 %p: returned\n", image );
120 128
 		break;
121 129
 
@@ -147,7 +155,7 @@ static int com32_exec_loop ( struct image *image ) {
147 155
 
148 156
 /**
149 157
  * Check image name extension
150
- * 
158
+ *
151 159
  * @v image		COM32 image
152 160
  * @ret rc		Return status code
153 161
  */
@@ -155,7 +163,7 @@ static int com32_identify ( struct image *image ) {
155 163
 	const char *ext;
156 164
 	static const uint8_t magic[] = { 0xB8, 0xFF, 0x4C, 0xCD, 0x21 };
157 165
 	uint8_t buf[5];
158
-	
166
+
159 167
 	if ( image->len >= 5 ) {
160 168
 		/* Check for magic number
161 169
 		 * mov eax,21cd4cffh

src/arch/i386/image/comboot.c → src/arch/x86/image/comboot.c View File

@@ -64,7 +64,7 @@ struct comboot_psp {
64 64
 
65 65
 /**
66 66
  * Copy command line to PSP
67
- * 
67
+ *
68 68
  * @v image		COMBOOT image
69 69
  */
70 70
 static void comboot_copy_cmdline ( struct image * image, userptr_t seg_userptr ) {
@@ -97,7 +97,7 @@ static void comboot_copy_cmdline ( struct image * image, userptr_t seg_userptr )
97 97
 
98 98
 /**
99 99
  * Initialize PSP
100
- * 
100
+ *
101 101
  * @v image		COMBOOT image
102 102
  * @v seg_userptr	segment to initialize
103 103
  */
@@ -213,7 +213,7 @@ static int comboot_exec_loop ( struct image *image ) {
213 213
 
214 214
 /**
215 215
  * Check image name extension
216
- * 
216
+ *
217 217
  * @v image		COMBOOT image
218 218
  * @ret rc		Return status code
219 219
  */
@@ -254,7 +254,7 @@ static int comboot_prepare_segment ( struct image *image )
254 254
 	seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 );
255 255
 
256 256
 	/* Allow etra 0x100 bytes before image for PSP */
257
-	filesz = image->len + 0x100; 
257
+	filesz = image->len + 0x100;
258 258
 
259 259
 	/* Ensure the entire 64k segment is free */
260 260
 	memsz = 0xFFFF;
@@ -289,7 +289,7 @@ static int comboot_probe ( struct image *image ) {
289 289
 
290 290
 	/* Check if this is a COMBOOT image */
291 291
 	if ( ( rc = comboot_identify ( image ) ) != 0 ) {
292
-		
292
+
293 293
 		return rc;
294 294
 	}
295 295
 
@@ -304,7 +304,7 @@ static int comboot_probe ( struct image *image ) {
304 304
  */
305 305
 static int comboot_exec ( struct image *image ) {
306 306
 	int rc;
307
-	
307
+
308 308
 	/* Sanity check for filesize */
309 309
 	if( image->len >= 0xFF00 ) {
310 310
 		DBGC( image, "COMBOOT %p: image too large\n",

src/arch/i386/include/comboot.h → src/arch/x86/include/comboot.h View File

@@ -29,7 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
29 29
 #define COMBOOT_FEATURE_LOCAL_BOOT (1 << 0)
30 30
 #define COMBOOT_FEATURE_IDLE_LOOP  (1 << 1)
31 31
 
32
-/** Maximum number of shuffle descriptors for 
32
+/** Maximum number of shuffle descriptors for
33 33
  * shuffle and boot functions
34 34
  * (INT 22h AX=0012h, 001Ah, 001Bh)
35 35
  */
@@ -102,7 +102,7 @@ typedef struct {
102 102
 extern void hook_comboot_interrupts ( );
103 103
 extern void unhook_comboot_interrupts ( );
104 104
 
105
-/* These are not the correct prototypes, but it doens't matter, 
105
+/* These are not the correct prototypes, but it doens't matter,
106 106
  * as we only ever get the address of these functions;
107 107
  * they are only called from COM32 code running in PHYS_CODE
108 108
  */
@@ -116,8 +116,6 @@ extern int comboot_resolv ( const char *name, struct in_addr *address );
116 116
 /* setjmp/longjmp context buffer used to return after loading an image */
117 117
 extern rmjmp_buf comboot_return;
118 118
 
119
-extern void *com32_external_esp;
120
-
121 119
 #define COMBOOT_EXIT 1
122 120
 #define COMBOOT_EXIT_RUN_KERNEL 2
123 121
 #define COMBOOT_EXIT_COMMAND 3

src/arch/i386/interface/syslinux/com32_call.c → src/arch/x86/interface/syslinux/com32_call.c View File

@@ -46,6 +46,9 @@ uint16_t __bss16 ( com32_saved_sp );
46 46
  */
47 47
 void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
48 48
 
49
+	DBGC ( &com32_regs, "COM32 INT%x in %#08lx out %#08lx\n",
50
+	       interrupt, inregs_phys, outregs_phys );
51
+
49 52
 	memcpy_user ( virt_to_user( &com32_regs ), 0,
50 53
 	              phys_to_user ( inregs_phys ), 0,
51 54
 	              sizeof(com32sys_t) );
@@ -76,7 +79,7 @@ void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physad
76 79
 		            /* patch INT instruction */
77 80
 		            "pushw %%ax\n\t"
78 81
 		            "movb %%ss:(com32_int_vector), %%al\n\t"
79
-		            "movb %%al, %%cs:(com32_intcall_instr + 1)\n\t" 
82
+		            "movb %%al, %%cs:(com32_intcall_instr + 1)\n\t"
80 83
 		            /* perform a jump to avoid problems with cache
81 84
 		             * consistency in self-modifying code on some CPUs (486)
82 85
 		             */
@@ -106,7 +109,7 @@ void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physad
106 109
 
107 110
 	if ( outregs_phys ) {
108 111
 		memcpy_user ( phys_to_user ( outregs_phys ), 0,
109
-		              virt_to_user( &com32_regs ), 0, 
112
+		              virt_to_user( &com32_regs ), 0,
110 113
 		              sizeof(com32sys_t) );
111 114
 	}
112 115
 }
@@ -116,6 +119,9 @@ void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physad
116 119
  */
117 120
 void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
118 121
 
122
+	DBGC ( &com32_regs, "COM32 farcall %04x:%04x in %#08lx out %#08lx\n",
123
+	       ( proc >> 16 ), ( proc & 0xffff ), inregs_phys, outregs_phys );
124
+
119 125
 	memcpy_user ( virt_to_user( &com32_regs ), 0,
120 126
 	              phys_to_user ( inregs_phys ), 0,
121 127
 	              sizeof(com32sys_t) );
@@ -165,7 +171,7 @@ void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t
165 171
 
166 172
 	if ( outregs_phys ) {
167 173
 		memcpy_user ( phys_to_user ( outregs_phys ), 0,
168
-		              virt_to_user( &com32_regs ), 0, 
174
+		              virt_to_user( &com32_regs ), 0,
169 175
 		              sizeof(com32sys_t) );
170 176
 	}
171 177
 }
@@ -176,13 +182,16 @@ void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t
176 182
 int __asmcall com32_cfarcall ( uint32_t proc, physaddr_t stack, size_t stacksz ) {
177 183
 	int32_t eax;
178 184
 
185
+	DBGC ( &com32_regs, "COM32 cfarcall %04x:%04x params %#08lx+%#zx\n",
186
+	       ( proc >> 16 ), ( proc & 0xffff ), stack, stacksz );
187
+
179 188
 	copy_user_to_rm_stack ( phys_to_user ( stack ), stacksz );
180 189
 	com32_farcall_proc = proc;
181 190
 
182 191
 	__asm__ __volatile__ (
183 192
 		REAL_CODE ( "lcall *%%ss:(com32_farcall_proc)\n\t" )
184 193
 		: "=a" (eax)
185
-		: 
194
+		:
186 195
 		: "ecx", "edx" );
187 196
 
188 197
 	remove_user_from_rm_stack ( 0, stacksz );

src/arch/i386/interface/syslinux/com32_wrapper.S → src/arch/x86/interface/syslinux/com32_wrapper.S View File

@@ -19,79 +19,82 @@
19 19
 
20 20
 FILE_LICENCE ( GPL2_OR_LATER )
21 21
 
22
+#include "librm.h"
23
+
22 24
 	.text
23
-	.arch i386
24
-	.code32
25 25
 
26
+	.code32
26 27
 	.globl com32_farcall_wrapper
27 28
 com32_farcall_wrapper:
29
+	movl	$VIRTUAL(com32_farcall), %eax
30
+	jmp	com32_wrapper
28 31
 
29
-	movl $com32_farcall, %eax
30
-	jmp com32_wrapper
31
-
32
-
32
+	.code32
33 33
 	.globl com32_cfarcall_wrapper
34 34
 com32_cfarcall_wrapper:
35
+	movl	$VIRTUAL(com32_cfarcall), %eax
36
+	jmp	com32_wrapper
35 37
 
36
-	movl $com32_cfarcall, %eax
37
-	jmp com32_wrapper
38
-
39
-
38
+	.code32
40 39
 	.globl com32_intcall_wrapper
41 40
 com32_intcall_wrapper:
41
+	movl	$VIRTUAL(com32_intcall), %eax
42
+	/* fall through */
42 43
 
43
-	movl $com32_intcall, %eax
44
-	/*jmp com32_wrapper*/ /* fall through */
45
-
44
+	.code32
46 45
 com32_wrapper:
46
+
47
+	/* Disable interrupts */
47 48
 	cli
48 49
 
49 50
 	/* Switch to internal virtual address space */
50
-	call _phys_to_virt
51
-
52
-	mov %eax, (com32_helper_function)
51
+	call	_phys_to_virt
53 52
 
54
-	/* Save external COM32 stack pointer */
55
-	movl %esp, (com32_external_esp)
53
+#ifdef __x86_64__
56 54
 
57
-	/* Copy arguments to caller-save registers */
58
-	movl 12(%esp), %eax
59
-	movl 8(%esp), %ecx
60
-	movl 4(%esp), %edx
55
+	.code64
61 56
 
62
-	/* Switch to internal stack */
63
-	movl (com32_internal_esp), %esp
57
+	/* Preserve registers which are callee-save for COM32 (i386 API) */
58
+	pushq	%rdi
59
+	pushq	%rsi
60
+	pushq	%rbp
64 61
 
65
-	/* Copy arguments to internal stack */
66
-	pushl %eax
67
-	pushl %ecx
68
-	pushl %edx
62
+	/* Extract parameters from stack */
63
+	movl	28(%rsp), %edi
64
+	movl	32(%rsp), %esi
65
+	movl	36(%rsp), %edx
69 66
 
70
-	call *(com32_helper_function)
67
+	/* Align stack pointer */
68
+	movq	%rsp, %rbp
69
+	andq	$~0x07, %rsp
71 70
 
72
-	/* Clean up stack */
73
-	addl $12, %esp
71
+	/* Call helper function */
72
+	movslq	%eax, %rax
73
+	call	*%rax
74 74
 
75
-	/* Save internal stack pointer and restore external stack pointer */
76
-	movl %esp, (com32_internal_esp)
77
-	movl (com32_external_esp), %esp
75
+	/* Restore stack pointer */
76
+	movq	%rbp, %rsp
78 77
 
79
-	/* Switch to external flat physical address space */
80
-	call _virt_to_phys
81
-
82
-	sti
83
-	ret
78
+	/* Restore registers */
79
+	popq	%rbp
80
+	popq	%rsi
81
+	popq	%rdi
84 82
 
83
+#else /* _x86_64 */
85 84
 
86
-	.data
85
+	/* Call helper function */
86
+	pushl	12(%esp)
87
+	pushl	12(%esp)
88
+	pushl	12(%esp)
89
+	call	*%eax
90
+	addl	$12, %esp
87 91
 
88
-/* Internal iPXE virtual address space %esp */
89
-.globl com32_internal_esp
90
-.lcomm com32_internal_esp, 4
92
+#endif /* _x86_64 */
91 93
 
92
-/* External flat physical address space %esp */
93
-.globl com32_external_esp
94
-.lcomm com32_external_esp, 4
94
+	/* Switch to external flat physical address space */
95
+	call	_virt_to_phys
96
+	.code32
95 97
 
96
-/* Function pointer of helper to call */
97
-.lcomm com32_helper_function, 4
98
+	/* Reenable interrupts and return */
99
+	sti
100
+	ret

src/arch/i386/interface/syslinux/comboot_call.c → src/arch/x86/interface/syslinux/comboot_call.c View File

@@ -489,7 +489,7 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
489 489
 			struct in_addr addr;
490 490
 
491 491
 			copy_from_user ( hostname, hostname_u, 0, len + 1 );
492
-			
492
+
493 493
 			/* TODO:
494 494
 			 * "If the hostname does not contain a dot (.), the
495 495
 			 * local domain name is automatically appended."
@@ -519,7 +519,7 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
519 519
 
520 520
 		/* Jump to real-mode entry point */
521 521
 		__asm__ __volatile__ (
522
-			REAL_CODE ( 
522
+			REAL_CODE (
523 523
 				"pushw %0\n\t"
524 524
 				"popw %%ds\n\t"
525 525
 				"pushl %1\n\t"

src/arch/i386/interface/syslinux/comboot_resolv.c → src/arch/x86/interface/syslinux/comboot_resolv.c View File


src/arch/i386/tests/comboot/shuffle-simple.asm → src/arch/x86/tests/comboot/shuffle-simple.asm View File

@@ -37,4 +37,3 @@ source:	dd 0
37 37
 	dd shuffle_len
38 38
 
39 39
 num_shuffle_descriptors equ 1
40
-

src/arch/i386/tests/comboot/version.asm → src/arch/x86/tests/comboot/version.asm View File


+ 64
- 2
src/arch/x86/transitions/librm.S View File

@@ -567,9 +567,10 @@ phys_to_prot:
567 567
 	popl	%eax
568 568
 	ret
569 569
 
570
-	/* Expose as _phys_to_virt for use by COMBOOT */
570
+.if32	/* Expose as _phys_to_virt for use by COMBOOT, if applicable */
571 571
 	.globl	_phys_to_virt
572 572
 	.equ	_phys_to_virt, phys_to_prot
573
+.endif
573 574
 
574 575
 /****************************************************************************
575 576
  * prot_to_phys (protected-mode near call, 32-bit virtual return address)
@@ -615,9 +616,10 @@ prot_to_phys:
615 616
 	popl	%eax
616 617
 	ret
617 618
 
618
-	/* Expose as _virt_to_phys for use by COMBOOT */
619
+.if32	/* Expose as _virt_to_phys for use by COMBOOT, if applicable */
619 620
 	.globl	_virt_to_phys
620 621
 	.equ	_virt_to_phys, prot_to_phys
622
+.endif
621 623
 
622 624
 /****************************************************************************
623 625
  * intr_to_prot (protected-mode near call, 32-bit virtual return address)
@@ -1202,6 +1204,66 @@ phys_call:
1202 1204
 	/* Return and discard function parameters */
1203 1205
 	ret	$( PHC_OFFSET_END - PHC_OFFSET_PARAMS )
1204 1206
 
1207
+/****************************************************************************
1208
+ * phys_to_long (protected-mode near call, 32-bit physical return address)
1209
+ *
1210
+ * Used by COMBOOT.
1211
+ *
1212
+ ****************************************************************************
1213
+ */
1214
+	.if64
1215
+
1216
+	.section ".text.phys_to_long", "ax", @progbits
1217
+	.code32
1218
+phys_to_long:
1219
+
1220
+	/* Switch to virtual addresses */
1221
+	call	phys_to_prot
1222
+
1223
+	/* Convert to 32-bit virtual return address */
1224
+	pushl	%eax
1225
+	movl	VIRTUAL(virt_offset), %eax
1226
+	subl	%eax, 4(%esp)
1227
+	popl	%eax
1228
+
1229
+	/* Switch to long mode and return */
1230
+	jmp	prot_to_long
1231
+
1232
+	/* Expose as _phys_to_virt for use by COMBOOT */
1233
+	.globl  _phys_to_virt
1234
+	.equ    _phys_to_virt, phys_to_long
1235
+
1236
+	.endif
1237
+
1238
+/****************************************************************************
1239
+ * long_to_phys (long-mode near call, 64-bit virtual return address)
1240
+ *
1241
+ * Used by COMBOOT.
1242
+ *
1243
+ ****************************************************************************
1244
+ */
1245
+	.if64
1246
+
1247
+	.section ".text.long_to_phys", "ax", @progbits
1248
+	.code64
1249
+long_to_phys:
1250
+
1251
+	/* Switch to protected mode */
1252
+	call	long_to_prot
1253
+	.code32
1254
+
1255
+	/* Convert to 32-bit virtual return address */
1256
+	popl	(%esp)
1257
+
1258
+	/* Switch to physical addresses and return */
1259
+	jmp	prot_to_phys
1260
+
1261
+	/* Expose as _virt_to_phys for use by COMBOOT */
1262
+	.globl  _virt_to_phys
1263
+	.equ    _virt_to_phys, long_to_phys
1264
+
1265
+	.endif
1266
+
1205 1267
 /****************************************************************************
1206 1268
  * flatten_real_mode (real-mode near call)
1207 1269
  *

Loading…
Cancel
Save