Browse Source

[prefix] Add PCI bus:dev.fn to ROM product string

This allows multiple gPXE ROMs in a system to be disambiguated at boot
time; the PCI ID will show up in the boot menu for a BBS-compliant BIOS.
tags/v0.9.4
Michael Brown 16 years ago
parent
commit
fd0aef9ee1
3 changed files with 131 additions and 95 deletions
  1. 56
    8
      src/arch/i386/prefix/libprefix.S
  2. 42
    75
      src/arch/i386/prefix/pxeprefix.S
  3. 33
    12
      src/arch/i386/prefix/romprefix.S

+ 56
- 8
src/arch/i386/prefix/libprefix.S View File

48
  *
48
  *
49
  * Parameters:
49
  * Parameters:
50
  *   %al : character to print
50
  *   %al : character to print
51
+ *   %ds:di : output buffer (or %di=0 to print to console)
51
  * Returns:
52
  * Returns:
52
- *   Nothing
53
- * Corrupts:
54
- *   %ax
53
+ *   %ds:di : next character in output buffer (if applicable)
55
  *****************************************************************************
54
  *****************************************************************************
56
  */
55
  */
57
 	.section ".prefix.lib"
56
 	.section ".prefix.lib"
59
 	.globl	print_character
58
 	.globl	print_character
60
 print_character:
59
 print_character:
61
 	/* Preserve registers */
60
 	/* Preserve registers */
61
+	pushw	%ax
62
 	pushw	%bx
62
 	pushw	%bx
63
 	pushw	%bp
63
 	pushw	%bp
64
-	/* Print character */
64
+	/* If %di is non-zero, write character to buffer and exit */
65
+	testw	%di, %di
66
+	jz	1f
67
+	movb	%al, %ds:(%di)
68
+	incw	%di
69
+	jmp	3f
70
+1:	/* Print character */
65
 	movw	$0x0007, %bx		/* page 0, attribute 7 (normal) */
71
 	movw	$0x0007, %bx		/* page 0, attribute 7 (normal) */
66
 	movb	$0x0e, %ah		/* write char, tty mode */
72
 	movb	$0x0e, %ah		/* write char, tty mode */
67
 	cmpb	$0x0a, %al		/* '\n'? */
73
 	cmpb	$0x0a, %al		/* '\n'? */
68
-	jne	1f
74
+	jne	2f
69
 	int	$0x10
75
 	int	$0x10
70
 	movb	$0x0d, %al
76
 	movb	$0x0d, %al
71
-1:	int	$0x10
77
+2:	int	$0x10
72
 	/* Restore registers and return */
78
 	/* Restore registers and return */
73
-	popw	%bp
79
+3:	popw	%bp
74
 	popw	%bx
80
 	popw	%bx
81
+	popw	%ax
75
 	ret
82
 	ret
76
 	.size	print_character, . - print_character
83
 	.size	print_character, . - print_character
77
 
84
 
80
  *
87
  *
81
  * Parameters:
88
  * Parameters:
82
  *   %ds:si : string to print
89
  *   %ds:si : string to print
90
+ *   %ds:di : output buffer (or %di=0 to print to console)
83
  * Returns:
91
  * Returns:
84
  *   %ds:si : character after terminating NUL
92
  *   %ds:si : character after terminating NUL
93
+ *   %ds:di : next character in output buffer (if applicable)
85
  *****************************************************************************
94
  *****************************************************************************
86
  */
95
  */
87
 	.section ".prefix.lib"
96
 	.section ".prefix.lib"
109
  *   %al : byte to print
118
  *   %al : byte to print
110
  *   %ax : word to print
119
  *   %ax : word to print
111
  *   %eax : dword to print
120
  *   %eax : dword to print
121
+ *   %ds:di : output buffer (or %di=0 to print to console)
112
  * Returns:
122
  * Returns:
113
- *   Nothing
123
+ *   %ds:di : next character in output buffer (if applicable)
114
  *****************************************************************************
124
  *****************************************************************************
115
  */
125
  */
116
 	.section ".prefix.lib"
126
 	.section ".prefix.lib"
151
 	ret
161
 	ret
152
 	.size	print_hex_nibble, . - print_hex_nibble
162
 	.size	print_hex_nibble, . - print_hex_nibble
153
 
163
 
164
+/*****************************************************************************
165
+ * Utility function: print PCI bus:dev.fn
166
+ *
167
+ * Parameters:
168
+ *   %ax : PCI bus:dev.fn to print
169
+ *   %ds:di : output buffer (or %di=0 to print to console)
170
+ * Returns:
171
+ *   %ds:di : next character in output buffer (if applicable)
172
+ *****************************************************************************
173
+ */
174
+	.section ".prefix.lib"
175
+	.code16
176
+	.globl	print_pci_busdevfn
177
+print_pci_busdevfn:
178
+	/* Preserve registers */
179
+	pushw	%ax
180
+	/* Print bus */
181
+	xchgb	%al, %ah
182
+	call	print_hex_byte
183
+	/* Print ":" */
184
+	movb	$':', %al
185
+	call	print_character
186
+	/* Print device */
187
+	movb	%ah, %al
188
+	shrb	$3, %al
189
+	call	print_hex_byte
190
+	/* Print "." */
191
+	movb	$'.', %al
192
+	call	print_character
193
+	/* Print function */
194
+	movb	%ah, %al
195
+	andb	$0x07, %al
196
+	call	print_hex_nibble
197
+	/* Restore registers and return */
198
+	popw	%ax
199
+	ret
200
+	.size	print_pci_busdevfn, . - print_pci_busdevfn
201
+
154
 /****************************************************************************
202
 /****************************************************************************
155
  * pm_call (real-mode near call)
203
  * pm_call (real-mode near call)
156
  *
204
  *

+ 42
- 75
src/arch/i386/prefix/pxeprefix.S View File

37
 	cld
37
 	cld
38
 	/* Print welcome message */
38
 	/* Print welcome message */
39
 	movw	$10f, %si
39
 	movw	$10f, %si
40
+	xorw	%di, %di
40
 	call	print_message
41
 	call	print_message
41
 	.section ".prefix.data"
42
 	.section ".prefix.data"
42
 10:	.asciz	"PXE->EB:"
43
 10:	.asciz	"PXE->EB:"
48
  */
49
  */
49
 detect_pxenv:
50
 detect_pxenv:
50
 	/* Signature check */
51
 	/* Signature check */
51
-	les	pxenv_segoff, %di
52
-	cmpl	$0x4e455850, %es:(%di)	/* 'PXEN' signature */
52
+	les	pxenv_segoff, %bx
53
+	cmpl	$0x4e455850, %es:(%bx)	/* 'PXEN' signature */
53
 	jne	no_pxenv
54
 	jne	no_pxenv
54
-	cmpw	$0x2b56, %es:4(%di)	/* 'V+' signature */
55
+	cmpw	$0x2b56, %es:4(%bx)	/* 'V+' signature */
55
 	jne	no_pxenv
56
 	jne	no_pxenv
56
 	/* Record entry point and UNDI segments */
57
 	/* Record entry point and UNDI segments */
57
-	pushl	%es:0x0a(%di)		/* Entry point */
58
+	pushl	%es:0x0a(%bx)		/* Entry point */
58
 	popl	entry_segoff
59
 	popl	entry_segoff
59
-	pushw	%es:0x24(%di)		/* UNDI code segment */
60
-	pushw	%es:0x26(%di)		/* UNDI code size */
60
+	pushw	%es:0x24(%bx)		/* UNDI code segment */
61
+	pushw	%es:0x26(%bx)		/* UNDI code size */
61
 	popl	undi_code_segoff
62
 	popl	undi_code_segoff
62
-	pushw	%es:0x20(%di)		/* UNDI data segment */
63
-	pushw	%es:0x22(%di)		/* UNDI data size */
63
+	pushw	%es:0x20(%bx)		/* UNDI data segment */
64
+	pushw	%es:0x22(%bx)		/* UNDI data size */
64
 	popl	undi_data_segoff
65
 	popl	undi_data_segoff
65
 	/* Print "PXENV+ at <address>" */
66
 	/* Print "PXENV+ at <address>" */
66
 	movw	$10f, %si
67
 	movw	$10f, %si
67
 	call	print_message
68
 	call	print_message
68
-	movw	%bx, %di
69
 	call	print_segoff
69
 	call	print_segoff
70
 	movb	$',', %al
70
 	movb	$',', %al
71
 	call	print_character
71
 	call	print_character
86
  */
86
  */
87
 detect_ppxe:
87
 detect_ppxe:
88
 	/* Signature check */
88
 	/* Signature check */
89
-	les	ppxe_segoff, %di
90
-	cmpl	$0x45585021, %es:(%di)	/* '!PXE' signature */
89
+	les	ppxe_segoff, %bx
90
+	cmpl	$0x45585021, %es:(%bx)	/* '!PXE' signature */
91
 	jne	no_ppxe
91
 	jne	no_ppxe
92
 	/* Record structure address, entry point, and UNDI segments */
92
 	/* Record structure address, entry point, and UNDI segments */
93
 	pushw	%es
93
 	pushw	%es
94
 	popw	ppxe_segment
94
 	popw	ppxe_segment
95
-	movw	%di, ppxe_offset
96
-	pushl	%es:0x10(%di)		/* Entry point */
95
+	movw	%bx, ppxe_offset
96
+	pushl	%es:0x10(%bx)		/* Entry point */
97
 	popl	entry_segoff
97
 	popl	entry_segoff
98
-	pushw	%es:0x30(%di)		/* UNDI code segment */
99
-	pushw	%es:0x36(%di)		/* UNDI code size */
98
+	pushw	%es:0x30(%bx)		/* UNDI code segment */
99
+	pushw	%es:0x36(%bx)		/* UNDI code size */
100
 	popl	undi_code_segoff
100
 	popl	undi_code_segoff
101
-	pushw	%es:0x28(%di)		/* UNDI data segment */
102
-	pushw	%es:0x2e(%di)		/* UNDI data size */
101
+	pushw	%es:0x28(%bx)		/* UNDI data segment */
102
+	pushw	%es:0x2e(%bx)		/* UNDI data size */
103
 	popl	undi_data_segoff
103
 	popl	undi_data_segoff
104
 	/* Print "!PXE at <address>" */
104
 	/* Print "!PXE at <address>" */
105
 	movw	$10f, %si
105
 	movw	$10f, %si
167
 	/* Print entry point */
167
 	/* Print entry point */
168
 	movw	$10f, %si
168
 	movw	$10f, %si
169
 	call	print_message
169
 	call	print_message
170
-	les	entry_segoff, %di
170
+	les	entry_segoff, %bx
171
 	call	print_segoff
171
 	call	print_segoff
172
 	.section ".prefix.data"
172
 	.section ".prefix.data"
173
 10:	.asciz	" entry point at "
173
 10:	.asciz	" entry point at "
175
 	/* Print UNDI code segment */
175
 	/* Print UNDI code segment */
176
 	movw	$10f, %si
176
 	movw	$10f, %si
177
 	call	print_message
177
 	call	print_message
178
-	les	undi_code_segoff, %di
178
+	les	undi_code_segoff, %bx
179
 	call	print_segoff
179
 	call	print_segoff
180
 	.section ".prefix.data"
180
 	.section ".prefix.data"
181
 10:	.asciz	"\n         UNDI code segment "
181
 10:	.asciz	"\n         UNDI code segment "
183
 	/* Print UNDI data segment */
183
 	/* Print UNDI data segment */
184
 	movw	$10f, %si
184
 	movw	$10f, %si
185
 	call	print_message
185
 	call	print_message
186
-	les	undi_data_segoff, %di
186
+	les	undi_data_segoff, %bx
187
 	call	print_segoff
187
 	call	print_segoff
188
 	.section ".prefix.data"
188
 	.section ".prefix.data"
189
 10:	.asciz	", data segment "
189
 10:	.asciz	", data segment "
271
 	call	print_pxe_error
271
 	call	print_pxe_error
272
 	jmp	99f
272
 	jmp	99f
273
 1:	/* Free base memory used by PXE base code */
273
 1:	/* Free base memory used by PXE base code */
274
-	movw	%fs:(0x13), %si
275
-	movw	undi_fbms_start, %di
274
+	movw	undi_fbms_start, %ax
275
+	movw	%fs:(0x13), %bx
276
 	call	free_basemem
276
 	call	free_basemem
277
 99:
277
 99:
278
 
278
 
289
 	call	print_pxe_error
289
 	call	print_pxe_error
290
 	jmp	99f
290
 	jmp	99f
291
 1:	/* Free base memory used by UNDI */
291
 1:	/* Free base memory used by UNDI */
292
-	movw	undi_fbms_start, %si
293
-	movw	undi_fbms_end, %di
292
+	movw	undi_fbms_end, %ax
293
+	movw	undi_fbms_start, %bx
294
 	call	free_basemem
294
 	call	free_basemem
295
 	/* Clear UNDI_FL_STARTED */
295
 	/* Clear UNDI_FL_STARTED */
296
 	andw	$~UNDI_FL_STARTED, flags
296
 	andw	$~UNDI_FL_STARTED, flags
324
  * Subroutine: print segment:offset address
324
  * Subroutine: print segment:offset address
325
  *
325
  *
326
  * Parameters:
326
  * Parameters:
327
- *   %es:%di : segment:offset address to print
327
+ *   %es:%bx : segment:offset address to print
328
+ *   %ds:di : output buffer (or %di=0 to print to console)
328
  * Returns:
329
  * Returns:
329
- *   Nothing
330
+ *   %ds:di : next character in output buffer (if applicable)
330
  *****************************************************************************
331
  *****************************************************************************
331
  */
332
  */
332
 print_segoff:
333
 print_segoff:
337
 	call	print_hex_word
338
 	call	print_hex_word
338
 	movb	$':', %al
339
 	movb	$':', %al
339
 	call	print_character
340
 	call	print_character
340
-	movw	%di, %ax
341
+	movw	%bx, %ax
341
 	call	print_hex_word
342
 	call	print_hex_word
342
 	/* Restore registers and return */
343
 	/* Restore registers and return */
343
 	popw	%ax
344
 	popw	%ax
348
  *
349
  *
349
  * Parameters:
350
  * Parameters:
350
  *   %ax : word to print
351
  *   %ax : word to print
352
+ *   %ds:di : output buffer (or %di=0 to print to console)
351
  * Returns:
353
  * Returns:
352
- *   Nothing
354
+ *   %ds:di : next character in output buffer (if applicable)
353
  *****************************************************************************
355
  *****************************************************************************
354
  */
356
  */
355
 print_word:
357
 print_word:
378
 	popw	%ax
380
 	popw	%ax
379
 	ret
381
 	ret
380
 	
382
 	
381
-/*****************************************************************************
382
- * Subroutine: print PCI bus:dev.fn
383
- *
384
- * Parameters:
385
- *   %ax : PCI bus:dev.fn to print
386
- * Returns:
387
- *   Nothing
388
- *****************************************************************************
389
- */
390
-print_pci_busdevfn:
391
-	/* Preserve registers */
392
-	pushw	%ax
393
-	/* Print bus */
394
-	xchgb	%al, %ah
395
-	call	print_hex_byte
396
-	/* Print ":" */
397
-	movb	$':', %al
398
-	call	print_character
399
-	/* Print device */
400
-	movb	%ah, %al
401
-	shrb	$3, %al
402
-	call	print_hex_byte
403
-	/* Print "." */
404
-	movb	$'.', %al
405
-	call	print_character
406
-	/* Print function */
407
-	movb	%ah, %al
408
-	andb	$0x07, %al
409
-	call	print_hex_nibble
410
-	/* Restore registers and return */
411
-	popw	%ax
412
-	ret	
413
-
414
 /*****************************************************************************
383
 /*****************************************************************************
415
  * Subroutine: zero 1kB block of base memory
384
  * Subroutine: zero 1kB block of base memory
416
  *
385
  *
417
  * Parameters:
386
  * Parameters:
418
- *   %si : block to zero (in kB)
387
+ *   %bx : block to zero (in kB)
419
  * Returns:
388
  * Returns:
420
  *   Nothing
389
  *   Nothing
421
  *****************************************************************************
390
  *****************************************************************************
427
 	pushw	%di
396
 	pushw	%di
428
 	pushw	%es
397
 	pushw	%es
429
 	/* Zero block */
398
 	/* Zero block */
430
-	movw	%si, %ax
399
+	movw	%bx, %ax
431
 	shlw	$6, %ax
400
 	shlw	$6, %ax
432
 	movw	%ax, %es
401
 	movw	%ax, %es
433
 	movw	$0x400, %cx
402
 	movw	$0x400, %cx
445
  * Subroutine: free and zero base memory
414
  * Subroutine: free and zero base memory
446
  *
415
  *
447
  * Parameters:
416
  * Parameters:
448
- *   %si : Expected current free base memory counter (in kB)
449
- *   %di : Desired new free base memory counter (in kB)
417
+ *   %ax : Desired new free base memory counter (in kB)
418
+ *   %bx : Expected current free base memory counter (in kB)
450
  *   %fs : BIOS data segment (0x40)
419
  *   %fs : BIOS data segment (0x40)
451
  * Returns:
420
  * Returns:
452
- *   %ax : Actual new free base memory counter (in kB)
421
+ *   None
453
  *
422
  *
454
- * The base memory from %si kB to %di kB is unconditionally zeroed.
423
+ * The base memory from %bx kB to %ax kB is unconditionally zeroed.
455
  * It will be freed if and only if the expected current free base
424
  * It will be freed if and only if the expected current free base
456
- * memory counter (%si) matches the actual current free base memory
425
+ * memory counter (%bx) matches the actual current free base memory
457
  * counter in 0x40:0x13; if this does not match then the memory will
426
  * counter in 0x40:0x13; if this does not match then the memory will
458
  * be leaked.
427
  * be leaked.
459
  *****************************************************************************
428
  *****************************************************************************
460
  */
429
  */
461
 free_basemem:
430
 free_basemem:
462
 	/* Zero base memory */
431
 	/* Zero base memory */
463
-	pushw	%si
464
-1:	cmpw	%si, %di
432
+	pushw	%bx
433
+1:	cmpw	%bx, %ax
465
 	je	2f
434
 	je	2f
466
 	call	zero_kb
435
 	call	zero_kb
467
-	incw	%si
436
+	incw	%bx
468
 	jmp	1b
437
 	jmp	1b
469
-2:	popw	%si
438
+2:	popw	%bx
470
 	/* Free base memory */
439
 	/* Free base memory */
471
-	movw	%fs:(0x13), %ax		/* Current FBMS to %ax */
472
-	cmpw	%ax, %si		/* Update FBMS only if "old" value  */
440
+	cmpw	%fs:(0x13), %bx		/* Update FBMS only if "old" value  */
473
 	jne	1f			/* is correct			    */
441
 	jne	1f			/* is correct			    */
474
-	movw	%di, %ax
475
 1:	movw	%ax, %fs:(0x13)
442
 1:	movw	%ax, %fs:(0x13)
476
 	ret
443
 	ret
477
 
444
 

+ 33
- 12
src/arch/i386/prefix/romprefix.S View File

85
 	.equ pnpheader_len, . - pnpheader
85
 	.equ pnpheader_len, . - pnpheader
86
 	.size pnpheader, . - pnpheader
86
 	.size pnpheader, . - pnpheader
87
 
87
 
88
+/* Manufacturer string */
88
 mfgstr:
89
 mfgstr:
89
 	.asciz	"http://etherboot.org"
90
 	.asciz	"http://etherboot.org"
90
 	.size mfgstr, . - mfgstr
91
 	.size mfgstr, . - mfgstr
92
+
93
+/* Product string
94
+ *
95
+ * Defaults to "gPXE".  If the ROM image is writable at initialisation
96
+ * time, it will be filled in to include the PCI bus:dev.fn number of
97
+ * the card as well.
98
+ */
91
 prodstr:
99
 prodstr:
92
-	.asciz	"gPXE"
100
+	.ascii	"gPXE"
101
+prodstr_separator:
102
+	.byte	0
103
+	.ascii	"(PCI "
104
+prodstr_pci_id:
105
+	.asciz	"xx:xx.x)"		/* Filled in by init code */
93
 	.size prodstr, . - prodstr
106
 	.size prodstr, . - prodstr
94
 	
107
 	
95
 undiheader:
108
 undiheader:
120
 	cld
133
 	cld
121
 	pushw	%cs
134
 	pushw	%cs
122
 	popw	%ds
135
 	popw	%ds
136
+	movw	%di, %bx
137
+	xorw	%di, %di
123
 	/* Print message as early as possible */
138
 	/* Print message as early as possible */
124
 	movw	$init_message, %si
139
 	movw	$init_message, %si
125
 	call	print_message
140
 	call	print_message
141
+	call	print_pci_busdevfn
142
+	/* Fill in product name string, if possible */
143
+	movw	$prodstr_pci_id, %di
144
+	call	print_pci_busdevfn
145
+	movb	$' ', prodstr_separator
146
+	xorw	%di, %di
126
 	/* Check for PnP BIOS */
147
 	/* Check for PnP BIOS */
127
-	testw	$0x0f, %di	/* PnP signature must be aligned - bochs    */
148
+	testw	$0x0f, %bx	/* PnP signature must be aligned - bochs    */
128
 	jnz	hook_int19	/* uses unalignment to indicate 'fake' PnP. */
149
 	jnz	hook_int19	/* uses unalignment to indicate 'fake' PnP. */
129
-	cmpl	$PNP_SIGNATURE, %es:0(%di)
150
+	cmpl	$PNP_SIGNATURE, %es:0(%bx)
130
 	jne	hook_int19
151
 	jne	hook_int19
131
 	/* Is PnP: print PnP message */
152
 	/* Is PnP: print PnP message */
132
 	movw	$init_message_pnp, %si
153
 	movw	$init_message_pnp, %si
133
 	call	print_message
154
 	call	print_message
134
-	xchgw	%bx, %bx
135
 	/* Check for BBS */
155
 	/* Check for BBS */
136
-	pushw	%es:0x1b(%di)	/* Real-mode data segment */
156
+	pushw	%es:0x1b(%bx)	/* Real-mode data segment */
137
 	pushw	%ds		/* &(bbs_version) */
157
 	pushw	%ds		/* &(bbs_version) */
138
 	pushw	$bbs_version
158
 	pushw	$bbs_version
139
 	pushw	$PNP_GET_BBS_VERSION
159
 	pushw	$PNP_GET_BBS_VERSION
140
-	lcall	*%es:0xd(%di)
160
+	lcall	*%es:0xd(%bx)
141
 	addw	$8, %sp
161
 	addw	$8, %sp
142
 	testw	%ax, %ax
162
 	testw	%ax, %ax
143
 	jne	hook_int19
163
 	jne	hook_int19
155
 	popl	%es:( 0x19 * 4 )
175
 	popl	%es:( 0x19 * 4 )
156
 hook_bbs:
176
 hook_bbs:
157
 	/* Check for PMM */
177
 	/* Check for PMM */
158
-	movw	$( 0xe000 - 1 ), %di
178
+	movw	$( 0xe00 - 1 ), %bx
159
 pmm_scan:
179
 pmm_scan:
160
-	incw	%di
180
+	incw	%bx
161
 	jz	no_pmm
181
 	jz	no_pmm
162
-	movw	%di, %es
182
+	movw	%bx, %es
163
 	cmpl	$PMM_SIGNATURE, %es:0
183
 	cmpl	$PMM_SIGNATURE, %es:0
164
 	jne	pmm_scan
184
 	jne	pmm_scan
165
-	xorw	%bx, %bx
185
+	xorw	%dx, %dx
166
 	xorw	%si, %si
186
 	xorw	%si, %si
167
 	movzbw	%es:5, %cx
187
 	movzbw	%es:5, %cx
168
 1:	es lodsb
188
 1:	es lodsb
169
-	addb	%al, %bl
189
+	addb	%al, %dl
170
 	loop	1b
190
 	loop	1b
171
 	jnz	pmm_scan
191
 	jnz	pmm_scan
172
 	/* PMM found: print PMM message */
192
 	/* PMM found: print PMM message */
221
 	.size init, . - init
241
 	.size init, . - init
222
 
242
 
223
 init_message:
243
 init_message:
224
-	.asciz	"gPXE (http://etherboot.org) -"
244
+	.asciz	"gPXE (http://etherboot.org) - PCI "
225
 	.size	init_message, . - init_message
245
 	.size	init_message, . - init_message
226
 init_message_pnp:
246
 init_message_pnp:
227
 	.asciz	" PnP"
247
 	.asciz	" PnP"
292
 
312
 
293
 	/* Print message as soon as possible */
313
 	/* Print message as soon as possible */
294
 	movw	$exec_message, %si
314
 	movw	$exec_message, %si
315
+	xorw	%di, %di
295
 	call	print_message
316
 	call	print_message
296
 
317
 
297
 	/* Store magic word on BIOS stack and remember BIOS %ss:sp */
318
 	/* Store magic word on BIOS stack and remember BIOS %ss:sp */

Loading…
Cancel
Save