Fix 32-bit overflow in parallels image support
[qemu-kvm/fedora.git] / hw / extboot.c
blobb91d54f2f5edf67654dc5603a3e335caf2e2bf7e
1 /*
2 * Extended boot option ROM support.
4 * Copyright IBM, Corp. 2007
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
14 #include "hw.h"
15 #include "pc.h"
16 #include "isa.h"
17 #include "block.h"
19 /* Extended Boot ROM suport */
21 union extboot_cmd
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;
40 static void get_translated_chs(BlockDriverState *bs, int *c, int *h, int *s)
42 bdrv_get_geometry_hint(bs, c, h, s);
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;
61 /* what is the correct algorithm for this?? */
62 if (*h == 256) {
63 *h = 255;
64 *c = *c + 1;
68 static uint32_t extboot_read(void *opaque, uint32_t addr)
70 int *pcmd = opaque;
71 return *pcmd;
74 static void extboot_write_cmd(void *opaque, uint32_t addr, uint32_t value)
76 union extboot_cmd cmd;
77 BlockDriverState *bs = opaque;
78 int cylinders, heads, sectors, err;
79 uint64_t nb_sectors;
80 target_phys_addr_t pa = 0;
81 int blen = 0;
82 void *buf = NULL;
84 cpu_physical_memory_read((value & 0xFFFF) << 4, (uint8_t *)&cmd,
85 sizeof(cmd));
87 if (cmd.type == 0x01 || cmd.type == 0x02) {
88 pa = cmd.xfer.segment * 16 + cmd.xfer.offset;
89 blen = cmd.xfer.nb_sectors * 512;
90 buf = qemu_memalign(512, blen);
93 switch (cmd.type) {
94 case 0x00:
95 get_translated_chs(bs, &cylinders, &heads, &sectors);
96 bdrv_get_geometry(bs, &nb_sectors);
97 cmd.query_geometry.cylinders = cylinders;
98 cmd.query_geometry.heads = heads;
99 cmd.query_geometry.sectors = sectors;
100 cmd.query_geometry.nb_sectors = nb_sectors;
101 break;
102 case 0x01:
103 err = bdrv_read(bs, cmd.xfer.sector, buf, cmd.xfer.nb_sectors);
104 if (err)
105 printf("Read failed\n");
107 cpu_physical_memory_write(pa, buf, blen);
109 break;
110 case 0x02:
111 cpu_physical_memory_read(pa, buf, blen);
113 err = bdrv_write(bs, cmd.xfer.sector, buf, cmd.xfer.nb_sectors);
114 if (err)
115 printf("Write failed\n");
117 break;
120 cpu_physical_memory_write((value & 0xFFFF) << 4, (uint8_t *)&cmd,
121 sizeof(cmd));
122 if (buf)
123 qemu_free(buf);
126 void extboot_init(BlockDriverState *bs, int cmd)
128 int *pcmd;
130 pcmd = qemu_mallocz(sizeof(int));
132 *pcmd = cmd;
133 register_ioport_read(0x404, 1, 1, extboot_read, pcmd);
134 register_ioport_write(0x405, 1, 2, extboot_write_cmd, bs);