xref: /illumos-kvm-cmd/hw/extboot.c (revision 68396ea9)
1 /*
2  * Extended boot option ROM support.
3  *
4  * Copyright IBM, Corp. 2007
5  *
6  * Authors:
7  *  Anthony Liguori   <aliguori@us.ibm.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2.  See
10  * the COPYING file in the top-level directory.
11  *
12  */
13 
14 #include "hw.h"
15 #include "pc.h"
16 #include "isa.h"
17 #include "block.h"
18 
19 /* Extended Boot ROM suport */
20 
21 union extboot_cmd
22 {
23     uint16_t type;
24     struct {
25 	uint16_t type;
26 	uint16_t cylinders;
27 	uint16_t heads;
28 	uint16_t sectors;
29 	uint64_t nb_sectors;
30     } query_geometry;
31     struct {
32 	uint16_t type;
33 	uint16_t nb_sectors;
34 	uint16_t segment;
35 	uint16_t offset;
36 	uint64_t sector;
37     } xfer;
38 };
39 
get_translated_chs(BlockDriverState * bs,int * c,int * h,int * s)40 static void get_translated_chs(BlockDriverState *bs, int *c, int *h, int *s)
41 {
42     bdrv_get_geometry_hint(bs, c, h, s);
43 
44     if (*c <= 1024) {
45 	*c >>= 0;
46 	*h <<= 0;
47     } else if (*c <= 2048) {
48 	*c >>= 1;
49 	*h <<= 1;
50     } else if (*c <= 4096) {
51 	*c >>= 2;
52 	*h <<= 2;
53     } else if (*c <= 8192) {
54 	*c >>= 3;
55 	*h <<= 3;
56     } else {
57 	*c >>= 4;
58 	*h <<= 4;
59     }
60 
61     /* what is the correct algorithm for this?? */
62     if (*h == 256) {
63 	*h = 255;
64 	*c = *c + 1;
65     }
66 }
67 
extboot_write_cmd(void * opaque,uint32_t addr,uint32_t value)68 static void extboot_write_cmd(void *opaque, uint32_t addr, uint32_t value)
69 {
70     union extboot_cmd cmd;
71     BlockDriverState *bs = opaque;
72     int cylinders, heads, sectors, err;
73     uint64_t nb_sectors;
74     target_phys_addr_t pa = 0;
75     int blen = 0;
76     void *buf = NULL;
77 
78     cpu_physical_memory_read((value & 0xFFFF) << 4, (uint8_t *)&cmd,
79                              sizeof(cmd));
80 
81     if (cmd.type == 0x01 || cmd.type == 0x02) {
82 	pa = cmd.xfer.segment * 16 + cmd.xfer.offset;
83         blen = cmd.xfer.nb_sectors * 512;
84         buf = qemu_memalign(512, blen);
85     }
86 
87     switch (cmd.type) {
88     case 0x00:
89         get_translated_chs(bs, &cylinders, &heads, &sectors);
90 	bdrv_get_geometry(bs, &nb_sectors);
91 	cmd.query_geometry.cylinders = cylinders;
92 	cmd.query_geometry.heads = heads;
93 	cmd.query_geometry.sectors = sectors;
94 	cmd.query_geometry.nb_sectors = nb_sectors;
95 	break;
96     case 0x01:
97 	err = bdrv_read(bs, cmd.xfer.sector, buf, cmd.xfer.nb_sectors);
98 	if (err)
99 	    printf("Read failed\n");
100 
101         cpu_physical_memory_write(pa, buf, blen);
102 
103 	break;
104     case 0x02:
105         cpu_physical_memory_read(pa, buf, blen);
106 
107 	err = bdrv_write(bs, cmd.xfer.sector, buf, cmd.xfer.nb_sectors);
108 	if (err)
109 	    printf("Write failed\n");
110 
111 	break;
112     }
113 
114     cpu_physical_memory_write((value & 0xFFFF) << 4, (uint8_t *)&cmd,
115                               sizeof(cmd));
116     if (buf)
117         qemu_free(buf);
118 }
119 
extboot_init(BlockDriverState * bs)120 void extboot_init(BlockDriverState *bs)
121 {
122     register_ioport_write(0x405, 1, 2, extboot_write_cmd, bs);
123 }
124