~ubuntu-branches/ubuntu/wily/qemu-kvm-spice/wily

« back to all changes in this revision

Viewing changes to pc-bios/optionrom/extboot.S

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-10-19 10:44:56 UTC
  • Revision ID: james.westby@ubuntu.com-20111019104456-xgvskumk3sxi97f4
Tags: upstream-0.15.0+noroms
ImportĀ upstreamĀ versionĀ 0.15.0+noroms

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Extended Boot Option ROM
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
17
 *
 
18
 * Copyright IBM Corporation, 2007
 
19
 *   Authors: Anthony Liguori <aliguori@us.ibm.com>
 
20
 */
 
21
 
 
22
#define OLD_INT19       (0x80 * 4)      /* re-use INT 0x80 BASIC vector */
 
23
#define OLD_INT13       (0x81 * 4)      /* re-use INT 0x81 BASIC vector */
 
24
 
 
25
.code16
 
26
.text
 
27
        .global _start
 
28
_start:
 
29
        .short 0xaa55
 
30
        .byte (_end - _start) / 512
 
31
        push %eax
 
32
        push %ds
 
33
 
 
34
        /* setup ds so we can access the IVT */
 
35
        xor %ax, %ax
 
36
        mov %ax, %ds
 
37
 
 
38
        /* there is one more bootable HD */
 
39
        incb 0x0475
 
40
 
 
41
        /* save old int 19 */
 
42
        mov (0x19*4), %eax
 
43
        mov %eax, (OLD_INT19)
 
44
 
 
45
        /* install out int 19 handler */
 
46
        movw $int19_handler, (0x19*4)
 
47
        mov %cs, (0x19*4+2)
 
48
 
 
49
        pop %ds
 
50
        pop %eax
 
51
        lret
 
52
 
 
53
int19_handler:
 
54
        push %eax /* reserve space for lret */
 
55
        push %eax
 
56
        push %bx
 
57
        push %cx
 
58
        push %dx
 
59
        push %ds
 
60
 
 
61
        /* setup ds to access IVT */
 
62
        xor %ax, %ax
 
63
        mov %ax, %ds
 
64
 
 
65
        /* save old int 13 to int 2c */
 
66
        mov (0x13*4), %eax
 
67
        mov %eax, (OLD_INT13)
 
68
 
 
69
        /* install our int 13 handler */
 
70
        movw $int13_handler, (0x13*4)
 
71
        mov %cs, (0x13*4+2)
 
72
 
 
73
        /* restore previous int $0x19 handler */
 
74
        mov (OLD_INT19),%eax
 
75
        mov %eax,(0x19*4)
 
76
 
 
77
        /* write old handler as return address onto stack */
 
78
        push %bp
 
79
        mov %sp, %bp
 
80
        mov %eax, 14(%bp)
 
81
        pop %bp
 
82
 
 
83
        pop %ds
 
84
        pop %dx
 
85
        pop %cx
 
86
        pop %bx
 
87
        pop %eax
 
88
        lret
 
89
 
 
90
#define FLAGS_CF        0x01
 
91
 
 
92
/* The two macro below clear/set the carry flag to indicate the status
 
93
 * of the interrupt execution. It is not enough to issue a clc/stc instruction,
 
94
 * since the value of the flags register will be overwritten by whatever is
 
95
 * in the stack frame
 
96
 */
 
97
.macro clc_stack
 
98
        push %bp
 
99
        mov %sp, %bp
 
100
        /* 8 = 2 (bp, just pushed) + 2 (ip) + 3 (real mode interrupt frame) */
 
101
        and $(~FLAGS_CF), 8(%bp)
 
102
        pop %bp
 
103
.endm
 
104
 
 
105
.macro stc_stack
 
106
        push %bp
 
107
        /* 8 = 2 (bp, just pushed) + 2 (ip) + 3 (real mode interrupt frame) */
 
108
        or $(FLAGS_CF), 8(%bp)
 
109
        pop %bp
 
110
.endm
 
111
 
 
112
/* we clobber %bx */
 
113
.macro alloca size
 
114
        push %ds
 
115
        push %bp
 
116
        mov %sp, %bp  /* remember the current stack position */
 
117
 
 
118
        mov %ss, %bx
 
119
        mov %bx, %ds
 
120
 
 
121
        sub \size, %sp
 
122
        and $(~0x0F), %sp
 
123
        mov %sp, %bx
 
124
 
 
125
        push %bp
 
126
        mov 0(%bp), %bp
 
127
.endm
 
128
 
 
129
/* we clobber %bp */
 
130
.macro allocbpa size
 
131
        mov %sp, %bp  /* remember the current stack position */
 
132
        sub \size, %sp
 
133
        and $(~0x0F), %sp
 
134
        push %bp
 
135
        mov %sp, %bp
 
136
        add $2, %bp
 
137
.endm
 
138
 
 
139
.macro freea
 
140
        pop %sp
 
141
        add $2, %sp
 
142
        pop %ds
 
143
.endm
 
144
 
 
145
.macro freebpa
 
146
        pop %sp
 
147
.endm
 
148
 
 
149
.macro dump reg
 
150
        push %ax
 
151
        push %dx
 
152
 
 
153
        mov \reg, %ax
 
154
        mov $0x406, %dx
 
155
        outw %ax, %dx
 
156
 
 
157
        pop %dx
 
158
        pop %ax
 
159
.endm
 
160
 
 
161
.macro callout value
 
162
        push %bp
 
163
        push %bx
 
164
        mov %sp, %bp
 
165
        alloca $16
 
166
        push %ax
 
167
        push %dx
 
168
 
 
169
        mov %ax, 0(%bx)     /* ax */
 
170
        mov 0(%bp), %ax     /* bx */
 
171
        mov %ax, 2(%bx)
 
172
        mov %cx, 4(%bx)     /* cx */
 
173
        mov %dx, 6(%bx)     /* dx */
 
174
        mov %si, 8(%bx)     /* si */
 
175
        mov %ds, 10(%bx)    /* ds */
 
176
        mov %es, 12(%bx)    /* ds */
 
177
        movw \value, 14(%bx) /* value */
 
178
 
 
179
        mov %bx, %ax
 
180
        shr $4, %ax
 
181
        mov %ds, %dx
 
182
        add %dx, %ax
 
183
 
 
184
        mov $0x407, %dx
 
185
        outw %ax, %dx
 
186
 
 
187
        pop %dx
 
188
        pop %ax
 
189
        freea
 
190
        pop %bx
 
191
        pop %bp
 
192
.endm
 
193
 
 
194
send_command:
 
195
        push %bp
 
196
        mov %sp, %bp
 
197
        push %ax
 
198
        push %bx
 
199
        push %dx
 
200
 
 
201
        mov 4(%bp), %ax
 
202
        shr $4, %ax
 
203
        and $0x0FFF, %ax
 
204
        mov %ss, %bx
 
205
        add %bx, %ax
 
206
 
 
207
        mov $0x405, %dx
 
208
        outw %ax, %dx
 
209
 
 
210
        pop %dx
 
211
        pop %bx
 
212
        pop %ax
 
213
        pop %bp
 
214
 
 
215
        push %ax
 
216
        mov 2(%bx), %ax
 
217
        pop %ax
 
218
 
 
219
        ret
 
220
 
 
221
add32:  /* lo, hi, lo, hi */
 
222
        push %bp
 
223
        mov %sp, %bp
 
224
 
 
225
        movw 4(%bp), %cx  /* hi */
 
226
        movw 6(%bp), %dx  /* lo */
 
227
 
 
228
        add  10(%bp), %dx
 
229
        jnc 1f
 
230
        add $1, %cx
 
231
1:      add 8(%bp), %cx
 
232
 
 
233
        pop %bp
 
234
        ret
 
235
 
 
236
mul32:  /* lo,      hi,     lo,     hi */
 
237
        /* 10(%bp), 8(%bp), 6(%bp), 4(%bp) */
 
238
        push %bp
 
239
        mov %sp, %bp
 
240
        push %ax
 
241
        push %bx
 
242
 
 
243
        xor %cx, %cx
 
244
        xor %dx, %dx
 
245
 
 
246
        /* for (i = 0; i < 16;) */
 
247
        xor %bx, %bx
 
248
0:
 
249
        cmp $16, %bx
 
250
        jge 2f
 
251
 
 
252
        mov 6(%bp), %ax
 
253
        and $1, %ax
 
254
        cmp $1, %ax
 
255
        jne 1f
 
256
        push 10(%bp)
 
257
        push 8(%bp)
 
258
        push %dx
 
259
        push %cx
 
260
        call add32
 
261
        add $8, %sp
 
262
1:
 
263
        shlw $1, 8(%bp)
 
264
        movw 10(%bp), %ax
 
265
        and $0x8000, %ax
 
266
        cmp $0x8000, %ax
 
267
        jne 1f
 
268
        orw $1, 8(%bp)
 
269
1:
 
270
        shlw $1, 10(%bp)
 
271
        shrw $1, 6(%bp)
 
272
 
 
273
        /* i++) { */
 
274
        add $1, %bx
 
275
        jmp 0b
 
276
 
 
277
2:
 
278
        pop %bx
 
279
        pop %ax
 
280
        pop %bp
 
281
        ret
 
282
 
 
283
disk_reset:
 
284
        movb $0, %ah
 
285
        clc_stack
 
286
        ret
 
287
 
 
288
/* this really should be a function, not a macro but i'm lazy */
 
289
.macro read_write_disk_sectors cmd
 
290
        push %ax
 
291
        push %bx
 
292
        push %cx
 
293
        push %dx
 
294
        push %si
 
295
 
 
296
        push %bp
 
297
        sub $10, %sp
 
298
        mov %sp, %bp
 
299
 
 
300
        /* save nb_sectors */
 
301
        mov %al, 6(%bp)
 
302
        movb $0, 7(%bp)
 
303
 
 
304
        /* save buffer */
 
305
        mov %bx, 8(%bp)
 
306
 
 
307
        /* cylinders */
 
308
        xor %ax, %ax
 
309
        mov %cl, %al
 
310
        shl $2, %ax
 
311
        and $0x300, %ax
 
312
        mov %ch, %al
 
313
        mov %ax, 0(%bp)
 
314
 
 
315
        /* heads */
 
316
        xor %ax, %ax
 
317
        mov %dh, %al
 
318
        mov %ax, 2(%bp)
 
319
 
 
320
        /* sectors - 1 */
 
321
        xor %ax, %ax
 
322
        mov %cl, %al
 
323
        and $0x3F, %al
 
324
        sub $1, %ax
 
325
        mov %ax, 4(%bp)
 
326
 
 
327
        alloca $16
 
328
 
 
329
        movw $0, 0(%bx) /* read c,h,s */
 
330
        push %bx
 
331
        call send_command
 
332
        add $2, %sp
 
333
 
 
334
        mov 6(%bx), %ax /* total_sectors */
 
335
        mov 2(%bp), %si /* *= heads */
 
336
        mul %si
 
337
        add 4(%bp), %ax /* += sectors - 1 */
 
338
 
 
339
        push 4(%bx) /* total_heads */
 
340
        push $0
 
341
        push 6(%bx) /* total_sectors */
 
342
        push $0
 
343
        call mul32
 
344
        add $8, %sp
 
345
 
 
346
        push 0(%bp) /* cylinders */
 
347
        push $0
 
348
        push %dx
 
349
        push %cx
 
350
        call mul32
 
351
        add $8, %sp
 
352
 
 
353
        add %ax, %dx
 
354
        jnc 1f
 
355
        add $1, %cx
 
356
1:
 
357
        freea
 
358
 
 
359
        alloca $16
 
360
 
 
361
        movw \cmd, 0(%bx) /* read */
 
362
        movw 6(%bp), %ax /* nb_sectors */
 
363
        movw %ax, 2(%bx)
 
364
        movw %es, 4(%bx) /* segment */
 
365
        movw 8(%bp), %ax /* offset */
 
366
        mov %ax, 6(%bx)
 
367
        movw %dx, 8(%bx) /* sector */
 
368
        movw %cx, 10(%bx)
 
369
        movw $0, 12(%bx)
 
370
        movw $0, 14(%bx)
 
371
 
 
372
        push %bx
 
373
        call send_command
 
374
        add $2, %sp
 
375
 
 
376
        freea
 
377
 
 
378
        add $10, %sp
 
379
        pop %bp
 
380
 
 
381
        pop %si
 
382
        pop %dx
 
383
        pop %cx
 
384
        pop %bx
 
385
        pop %ax
 
386
 
 
387
        mov $0, %ah
 
388
        clc_stack
 
389
        ret
 
390
.endm
 
391
 
 
392
read_disk_sectors:
 
393
        read_write_disk_sectors $0x01
 
394
 
 
395
write_disk_sectors:
 
396
        read_write_disk_sectors $0x02
 
397
 
 
398
read_disk_drive_parameters:
 
399
        push %bx
 
400
 
 
401
        /* allocate memory for packet, pointer gets returned in bx */
 
402
        alloca $16
 
403
 
 
404
        /* issue command */
 
405
        movw $0, 0(%bx) /* cmd = 0, read c,h,s */
 
406
        push %bx
 
407
        call send_command
 
408
        add $2, %sp
 
409
 
 
410
        /* normalize sector value */
 
411
        movb 6(%bx), %cl
 
412
        andb $0x3F, %cl
 
413
        movb %cl, 6(%bx)
 
414
 
 
415
        /* normalize cylinders */
 
416
        subw $2, 2(%bx)
 
417
 
 
418
        /* normalize heads */
 
419
        subw $1, 4(%bx)
 
420
 
 
421
        /* return code */
 
422
        mov $0, %ah
 
423
 
 
424
        /* cylinders */
 
425
        movb 2(%bx), %ch
 
426
        movb 3(%bx), %cl
 
427
        shlb $6, %cl
 
428
        andb $0xC0, %cl
 
429
 
 
430
        /* sectors */
 
431
        orb 6(%bx), %cl
 
432
 
 
433
        /* heads */
 
434
        movb 4(%bx), %dh
 
435
 
 
436
        /* drives */
 
437
        movb $1, %dl
 
438
 
 
439
        /* status */
 
440
        mov $0, %ah
 
441
 
 
442
        freea
 
443
 
 
444
        pop %bx
 
445
 
 
446
        /* do this last since it's the most sensitive */
 
447
        clc_stack
 
448
        ret
 
449
 
 
450
alternate_disk_reset:
 
451
        movb $0, %ah
 
452
        clc_stack
 
453
        ret
 
454
 
 
455
read_disk_drive_size:
 
456
        push %bx
 
457
        alloca $16
 
458
 
 
459
        movw $0, 0(%bx) /* cmd = 0, read c,h,s */
 
460
        push %bx
 
461
        call send_command
 
462
        add $2, %sp
 
463
 
 
464
        /* cylinders - 1 to cx:dx */
 
465
        mov 2(%bx), %dx
 
466
        xor %cx, %cx
 
467
        sub $1, %dx
 
468
 
 
469
        /* heads */
 
470
        push 4(%bx)
 
471
        push $0
 
472
        push %dx
 
473
        push %cx
 
474
        call mul32
 
475
        add $8, %sp
 
476
 
 
477
        /* sectors */
 
478
        push 6(%bx)
 
479
        push $0
 
480
        push %dx
 
481
        push %cx
 
482
        call mul32
 
483
        add $8, %sp
 
484
 
 
485
        /* status */
 
486
        mov $3, %ah
 
487
 
 
488
        freea
 
489
        pop %bx
 
490
 
 
491
        clc_stack
 
492
        ret
 
493
 
 
494
check_if_extensions_present:
 
495
        mov $0x30, %ah
 
496
        mov $0xAA55, %bx
 
497
        mov $0x07, %cx
 
498
        clc_stack
 
499
        ret
 
500
 
 
501
.macro extended_read_write_sectors cmd
 
502
        cmpb $10, 0(%si)
 
503
        jg 1f
 
504
        mov $1, %ah
 
505
        stc_stack
 
506
        ret
 
507
1:
 
508
        push %ax
 
509
        push %bp
 
510
        allocbpa $16
 
511
 
 
512
        movw \cmd, 0(%bp) /* read */
 
513
        movw 2(%si), %ax   /* nb_sectors */
 
514
        movw %ax, 2(%bp)
 
515
        movw 4(%si), %ax   /* offset */
 
516
        movw %ax, 6(%bp)
 
517
        movw 6(%si), %ax   /* segment */
 
518
        movw %ax, 4(%bp)
 
519
        movw 8(%si), %ax   /* block */
 
520
        movw %ax, 8(%bp)
 
521
        movw 10(%si), %ax
 
522
        movw %ax, 10(%bp)
 
523
        movw 12(%si), %ax
 
524
        movw %ax, 12(%bp)
 
525
        movw 14(%si), %ax
 
526
        movw %ax, 14(%bp)
 
527
 
 
528
        push %bp
 
529
        call send_command
 
530
        add $2, %sp
 
531
 
 
532
        freebpa
 
533
        pop %bp
 
534
        pop %ax
 
535
 
 
536
        mov $0, %ah
 
537
        clc_stack
 
538
        ret
 
539
.endm
 
540
 
 
541
extended_read_sectors:
 
542
        extended_read_write_sectors $0x01
 
543
 
 
544
extended_write_sectors:
 
545
        extended_read_write_sectors $0x02
 
546
 
 
547
get_extended_drive_parameters:
 
548
        push %ax
 
549
        push %bp
 
550
        push %cx
 
551
        push %dx
 
552
 
 
553
        allocbpa $16
 
554
 
 
555
        movw $0, 0(%bp) /* read c,h,s */
 
556
        push %bp
 
557
        call send_command
 
558
        add $2, %sp
 
559
 
 
560
        /* write size */
 
561
        movw $26, 0(%si)
 
562
 
 
563
        /* set flags to 2 */
 
564
        movw $2, 2(%si)
 
565
 
 
566
        /* cylinders */
 
567
        mov 2(%bp), %ax
 
568
        mov %ax, 4(%si)
 
569
        xor %ax, %ax
 
570
        mov %ax, 6(%si)
 
571
 
 
572
        /* heads */
 
573
        mov 4(%bp), %ax
 
574
        mov %ax, 8(%si)
 
575
        xor %ax, %ax
 
576
        mov %ax, 10(%si)
 
577
 
 
578
        /* sectors */
 
579
        mov 6(%bp), %ax
 
580
        mov %ax, 12(%si)
 
581
        xor %ax, %ax
 
582
        mov %ax, 14(%si)
 
583
 
 
584
        /* set total number of sectors */
 
585
        mov 8(%bp), %ax
 
586
        mov %ax, 16(%si)
 
587
        mov 10(%bp), %ax
 
588
        mov %ax, 18(%si)
 
589
        mov 12(%bp), %ax
 
590
        mov %ax, 20(%si)
 
591
        mov 14(%bp), %ax
 
592
        mov %ax, 22(%si)
 
593
 
 
594
        /* number of bytes per sector */
 
595
        movw $512, 24(%si)
 
596
 
 
597
        freebpa
 
598
 
 
599
        pop %dx
 
600
        pop %cx
 
601
        pop %bp
 
602
        pop %ax
 
603
 
 
604
        mov $0, %ah
 
605
        clc_stack
 
606
        ret
 
607
 
 
608
terminate_disk_emulation:
 
609
        mov $1, %ah
 
610
        stc_stack
 
611
        ret
 
612
 
 
613
int13_handler:
 
614
        cmp $0x80, %dl
 
615
        je 1f
 
616
 
 
617
        /* write old handler as return address onto stack */
 
618
        push %eax
 
619
        push %eax
 
620
        push %ds
 
621
        push %bp
 
622
        mov %sp, %bp
 
623
        xor %ax, %ax
 
624
        mov %ax, %ds
 
625
        mov (OLD_INT13), %eax
 
626
        mov %eax, 8(%bp)
 
627
        pop %bp
 
628
        pop %ds
 
629
        pop %eax
 
630
        lret
 
631
1:
 
632
        cmp $0x0, %ah
 
633
        jne 1f
 
634
        call disk_reset
 
635
        iret
 
636
1:
 
637
        cmp $0x2, %ah
 
638
        jne 1f
 
639
        call read_disk_sectors
 
640
        iret
 
641
1:
 
642
        cmp $0x8, %ah
 
643
        jne 1f
 
644
        call read_disk_drive_parameters
 
645
        iret
 
646
1:
 
647
        cmp $0x15, %ah
 
648
        jne 1f
 
649
        call read_disk_drive_size
 
650
        iret
 
651
1:
 
652
        cmp $0x41, %ah
 
653
        jne 1f
 
654
        call check_if_extensions_present
 
655
        iret
 
656
1:
 
657
        cmp $0x42, %ah
 
658
        jne 1f
 
659
        call extended_read_sectors
 
660
        iret
 
661
1:
 
662
        cmp $0x48, %ah
 
663
        jne 1f
 
664
        call get_extended_drive_parameters
 
665
        iret
 
666
1:
 
667
        cmp $0x4b, %ah
 
668
        jne 1f
 
669
        call terminate_disk_emulation
 
670
        iret
 
671
1:
 
672
        cmp $0x0d, %ah
 
673
        jne 1f
 
674
        call alternate_disk_reset
 
675
        iret
 
676
1:
 
677
        cmp $0x03, %ah
 
678
        jne 1f
 
679
        call write_disk_sectors
 
680
        iret
 
681
1:
 
682
        cmp $0x43, %ah
 
683
        jne 1f
 
684
        call extended_write_sectors
 
685
        iret
 
686
1:
 
687
        int $0x18  /* boot failed */
 
688
        iret
 
689
 
 
690
.align 512, 0
 
691
_end: