bdrv_set_boot_sector(drives_table[hda].bdrv, bootsect, sizeof(bootsect));
}
-static int load_kernel(const char *filename, uint8_t *addr,
- uint8_t *real_addr)
-{
- int fd, size;
- int setup_sects;
-
- fd = open(filename, O_RDONLY | O_BINARY);
- if (fd < 0)
- return -1;
-
- /* load 16 bit code */
- if (qemu_read_ok(fd, real_addr, 512) < 0)
- goto fail;
- setup_sects = real_addr[0x1F1];
- if (!setup_sects)
- setup_sects = 4;
- if (qemu_read_ok(fd, real_addr + 512, setup_sects * 512) < 0)
- goto fail;
-
- /* load 32 bit code */
- size = qemu_read(fd, addr, 16 * 1024 * 1024);
- if (size < 0)
- goto fail;
- close(fd);
- return size;
- fail:
- close(fd);
- return -1;
-}
-
static long get_file_size(FILE *f)
{
long where, size;
return size;
}
+static void pstrcpy_targphys(target_phys_addr_t dest, int buf_size,
+ const char *source)
+{
+ static const char nul_byte;
+ const char *nulp;
+
+ if (buf_size <= 0) return;
+ nulp = memchr(source, 0, buf_size);
+ if (nulp) {
+ cpu_physical_memory_write(dest, source, (nulp - source) + 1);
+ } else {
+ cpu_physical_memory_write(dest, source, buf_size - 1);
+ cpu_physical_memory_write(dest, &nul_byte, 1);
+ }
+}
+
static void load_linux(const char *kernel_filename,
const char *initrd_filename,
const char *kernel_cmdline)
int setup_size, kernel_size, initrd_size, cmdline_size;
uint32_t initrd_max;
uint8_t header[1024];
- uint8_t *real_addr, *prot_addr, *cmdline_addr, *initrd_addr;
+ target_phys_addr_t real_addr, prot_addr, cmdline_addr, initrd_addr;
FILE *f, *fi;
/* Align to 16 bytes as a paranoia measure */
if (protocol < 0x200 || !(header[0x211] & 0x01)) {
/* Low kernel */
- real_addr = phys_ram_base + 0x90000;
- cmdline_addr = phys_ram_base + 0x9a000 - cmdline_size;
- prot_addr = phys_ram_base + 0x10000;
+ real_addr = 0x90000;
+ cmdline_addr = 0x9a000 - cmdline_size;
+ prot_addr = 0x10000;
} else if (protocol < 0x202) {
/* High but ancient kernel */
- real_addr = phys_ram_base + 0x90000;
- cmdline_addr = phys_ram_base + 0x9a000 - cmdline_size;
- prot_addr = phys_ram_base + 0x100000;
+ real_addr = 0x90000;
+ cmdline_addr = 0x9a000 - cmdline_size;
+ prot_addr = 0x100000;
} else {
/* High and recent kernel */
- real_addr = phys_ram_base + 0x10000;
- cmdline_addr = phys_ram_base + 0x20000;
- prot_addr = phys_ram_base + 0x100000;
+ real_addr = 0x10000;
+ cmdline_addr = 0x20000;
+ prot_addr = 0x100000;
}
#if 0
"qemu: real_addr = %#zx\n"
"qemu: cmdline_addr = %#zx\n"
"qemu: prot_addr = %#zx\n",
- real_addr-phys_ram_base,
- cmdline_addr-phys_ram_base,
- prot_addr-phys_ram_base);
+ real_addr,
+ cmdline_addr,
+ prot_addr);
#endif
/* highest address for loading the initrd */
initrd_max = ram_size-ACPI_DATA_SIZE-1;
/* kernel command line */
- pstrcpy((char*)cmdline_addr, 4096, kernel_cmdline);
+ pstrcpy_targphys(cmdline_addr, 4096, kernel_cmdline);
if (protocol >= 0x202) {
- stl_p(header+0x228, cmdline_addr-phys_ram_base);
+ stl_p(header+0x228, cmdline_addr);
} else {
stw_p(header+0x20, 0xA33F);
stw_p(header+0x22, cmdline_addr-real_addr);
}
initrd_size = get_file_size(fi);
- initrd_addr = phys_ram_base + ((initrd_max-initrd_size) & ~4095);
+ initrd_addr = ((initrd_max-initrd_size) & ~4095);
fprintf(stderr, "qemu: loading initrd (%#x bytes) at %#zx\n",
- initrd_size, initrd_addr-phys_ram_base);
+ initrd_size, initrd_addr);
- if (fread(initrd_addr, 1, initrd_size, fi) != initrd_size) {
+ if (!fread_targphys_ok(initrd_addr, initrd_size, fi)) {
fprintf(stderr, "qemu: read error on initial ram disk '%s'\n",
initrd_filename);
exit(1);
}
fclose(fi);
- stl_p(header+0x218, initrd_addr-phys_ram_base);
+ stl_p(header+0x218, initrd_addr);
stl_p(header+0x21c, initrd_size);
}
/* store the finalized header and load the rest of the kernel */
- memcpy(real_addr, header, 1024);
+ cpu_physical_memory_write(real_addr, header, 1024);
setup_size = header[0x1f1];
if (setup_size == 0)
setup_size = (setup_size+1)*512;
kernel_size -= setup_size; /* Size of protected-mode code */
- if (fread(real_addr+1024, 1, setup_size-1024, f) != setup_size-1024 ||
- fread(prot_addr, 1, kernel_size, f) != kernel_size) {
+ if (!fread_targphys_ok(real_addr+1024, setup_size-1024, f) ||
+ !fread_targphys_ok(prot_addr, kernel_size, f)) {
fprintf(stderr, "qemu: read error on kernel '%s'\n",
kernel_filename);
exit(1);
fclose(f);
/* generate bootsector to set up the initial register state */
- real_seg = (real_addr-phys_ram_base) >> 4;
+ real_seg = real_addr >> 4;
seg[0] = seg[2] = seg[3] = seg[4] = seg[4] = real_seg;
seg[1] = real_seg+0x20; /* CS */
memset(gpr, 0, sizeof gpr);
goto bios_error;
}
bios_offset = qemu_ram_alloc(bios_size);
- ret = load_image(buf, phys_ram_base + bios_offset);
+ ret = load_image_targphys(buf, bios_offset, bios_size);
if (ret != bios_size) {
bios_error:
fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", buf);
goto vga_bios_error;
vga_bios_offset = qemu_ram_alloc(65536);
- ret = load_image(buf, phys_ram_base + vga_bios_offset);
+ ret = load_image_targphys(buf, vga_bios_offset, vga_bios_size);
if (ret != vga_bios_size) {
vga_bios_error:
fprintf(stderr, "qemu: could not load VGA BIOS '%s'\n", buf);
if (size > (0x10000 - offset))
goto option_rom_error;
option_rom_offset = qemu_ram_alloc(size);
- ret = load_image(option_rom[i], phys_ram_base + option_rom_offset);
+ ret = load_image_targphys(option_rom[i], option_rom_offset, size);
if (ret != size) {
option_rom_error:
fprintf(stderr, "Too many option ROMS\n");
}
/* return the size or -1 if error */
+/* deprecated, because caller does not specify buffer size! */
int load_image(const char *filename, uint8_t *addr)
{
int fd, size;
return size;
}
+/* return the amount read, just like fread. 0 may mean error or eof */
+int fread_targphys(target_phys_addr_t dst_addr, size_t nbytes, FILE *f)
+{
+ unsigned char buf[4096];
+ target_phys_addr_t dst_begin = dst_addr;
+ size_t want, did;
+
+ while (nbytes) {
+ want = nbytes > sizeof(buf) ? sizeof(buf) : nbytes;
+ did = fread(buf, 1, want, f);
+ if (did != want) break;
+
+ cpu_physical_memory_write(dst_addr, buf, did);
+ dst_addr += did;
+ nbytes -= did;
+ }
+ return dst_addr - dst_begin;
+}
+
+/* returns 0 on error, 1 if ok */
+int fread_targphys_ok(target_phys_addr_t dst_addr, size_t nbytes, FILE *f)
+{
+ return fread_targphys(dst_addr, nbytes, f) == nbytes;
+}
+
+/* return the size or -1 if error */
+int load_image_targphys(const char *filename,
+ target_phys_addr_t addr, int max_sz)
+{
+ FILE *f;
+ size_t got;
+
+ f = fopen(filename, "rb");
+ if (!f) return -1;
+
+ got = fread_targphys(addr, max_sz, f);
+ if (ferror(f)) { fclose(f); return -1; }
+ fclose(f);
+
+ return got;
+}
+
/* A.OUT loader */
struct exec