From: Thiemo Seufer <ths@networkno.de>
To: Paul Brook <paul@codesourcery.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH] Add more devices for MIPS system emulation
Date: Mon, 6 Mar 2006 14:50:44 +0000 [thread overview]
Message-ID: <20060306145044.GB27785@networkno.de> (raw)
In-Reply-To: <200602232144.21423.paul@codesourcery.com>
On Thu, Feb 23, 2006 at 09:44:20PM +0000, Paul Brook wrote:
> > > > That's the current state since there is no real mips firmware, but Qemu
> > > > should also be able to boot from an image. E.g. Linux/MIPS on
> > > > DECstations uses MSDOS disklabels.
> > >
> > > I don't see how providing a fake an x86 boot sector would help this.
> > > Presumably the DECstation firmware just knows how to load an image from
> > > disk.
> >
> > It loads a block sector list from the bootsector which points to
> > the second stage bootloader.
>
> The existing linux.bin definitely won't do what you want then.
>
> In any case until the MIPS emulation can emulate a DECstation and we have a
> corresponding BIOS that we can distribute, your patch just breaks diskless
> MIPS emulation for no apparent benefit.
I updated the patch to allow for that again, and added an ELF loader on
top to avoid hardcoded kernel load addresses/entry points. This is also
useful for stand-alone programs. The ramdisk and command line addresses
are still hardcoded.
Thiemo
Index: qemu-work/Makefile.target
===================================================================
--- qemu-work.orig/Makefile.target 2006-02-21 16:41:47.000000000 +0000
+++ qemu-work/Makefile.target 2006-03-06 02:03:38.000000000 +0000
@@ -333,8 +333,11 @@
DEFINES += -DHAS_AUDIO
endif
ifeq ($(TARGET_ARCH), mips)
-VL_OBJS+= mips_r4k.o dma.o vga.o serial.o i8254.o i8259.o
-#VL_OBJS+= #ide.o pckbd.o fdc.o m48t59.o
+VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
+VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o mips_r4k.o
+VL_OBJS+= mixeng.o
+#VL_OBJS+= #fdc.o
+DEFINES += -DHAS_AUDIO
endif
ifeq ($(TARGET_BASE_ARCH), sparc)
ifeq ($(TARGET_ARCH), sparc64)
Index: qemu-work/hw/mips_r4k.c
===================================================================
--- qemu-work.orig/hw/mips_r4k.c 2006-02-21 16:40:03.000000000 +0000
+++ qemu-work/hw/mips_r4k.c 2006-03-06 02:07:18.000000000 +0000
@@ -1,12 +1,13 @@
#include "vl.h"
#define BIOS_FILENAME "mips_bios.bin"
-//#define BIOS_FILENAME "system.bin"
-#define KERNEL_LOAD_ADDR 0x80010000
+#define LINUX_BOOT_FILENAME "linux_boot.bin"
+
#define INITRD_LOAD_ADDR 0x80800000
extern FILE *logfile;
+static RTCState *rtc_state;
static PITState *pit;
static void pic_irq_request(void *opaque, int level)
@@ -101,6 +102,136 @@
cpu_mips_update_count(env, 1, 0);
}
+#define REG_EQUIPMENT_BYTE 0x14
+#define REG_IBM_CENTURY_BYTE 0x32
+#define REG_IBM_PS2_CENTURY_BYTE 0x37
+
+static inline int to_bcd(RTCState *s, int a)
+{
+ return ((a / 10) << 4) | (a % 10);
+}
+
+static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table)
+{
+ RTCState *s = rtc_state;
+ int val;
+ time_t ti;
+ struct tm *tm;
+
+ /* set the CMOS date */
+ time(&ti);
+ if (rtc_utc)
+ tm = gmtime(&ti);
+ else
+ tm = localtime(&ti);
+ rtc_set_date(s, tm);
+
+ val = to_bcd(s, (tm->tm_year / 100) + 19);
+ rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
+ rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
+}
+
+
+#include "disas.h"
+
+#define ELF_CLASS ELFCLASS32
+#ifdef TARGET_WORDS_BIGENDIAN
+# define ELF_DATA ELFDATA2MSB
+#else
+# define ELF_DATA ELFDATA2LSB
+#endif
+#define ELF_ARCH EM_MIPS
+
+#include "elf.h"
+
+#ifndef BSWAP_NEEDED
+#define bswap_ehdr32(e) do { } while (0)
+#define bswap_phdr32(e) do { } while (0)
+#define bswap_shdr32(e) do { } while (0)
+#define bswap_sym32(e) do { } while (0)
+#endif
+
+#define SZ 32
+#define elf_word uint32_t
+#define bswapSZs bswap32s
+#include "elf_ops.h"
+
+static int load_mips_kernel_elf(const char *filename, elf_word *entry)
+{
+ struct elf32_hdr ehdr;
+ int retval, fd, i;
+ Elf32_Half machine;
+
+ fd = open(filename, O_RDONLY | O_BINARY);
+ if (fd < 0)
+ goto error;
+
+ retval = read(fd, &ehdr, sizeof(ehdr));
+ if (retval < 0)
+ goto error;
+
+ if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E'
+ || ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F')
+ goto error;
+ machine = tswap16(ehdr.e_machine);
+ if (machine == EM_MIPS) {
+ struct elf32_phdr phdr;
+
+ bswap_ehdr32(&ehdr);
+
+ *entry = ehdr.e_entry;
+ retval = lseek(fd, ehdr.e_phoff, SEEK_SET);
+ if (retval < 0)
+ goto error;
+
+ for (i = 0; i < ehdr.e_phnum; i++) {
+ retval = read(fd, &phdr, sizeof(phdr));
+ if (retval < 0)
+ goto error;
+ bswap_phdr32(&phdr);
+ if (phdr.p_type == PT_LOAD) {
+ uint8_t *addr;
+ size_t sz = phdr.p_filesz;
+
+ if (phdr.p_vaddr < 0x80000000
+ || phdr.p_memsz > 0x20000000
+ || (phdr.p_vaddr < 0xa0000000 && (phdr.p_vaddr + phdr.p_memsz) >= 0xa0000000)
+ || (phdr.p_vaddr < 0xc0000000 && (phdr.p_vaddr + phdr.p_memsz) >= 0xc0000000))
+ goto error;
+ addr = (uint8_t *)(phys_ram_base + (phdr.p_vaddr & 0x1fffffff));
+ retval = lseek(fd, phdr.p_offset, SEEK_SET);
+ if (retval < 0)
+ goto error;
+ while (sz) {
+ retval = read(fd, addr, sz);
+ switch (retval) {
+ case -1:
+ goto error;
+ case 0: /* EOF */
+ if (sz)
+ goto error;
+ break;
+ default:
+ if (sz < retval)
+ goto error;
+ sz -= retval;
+ retval = 0;
+ break;
+ }
+ }
+ }
+ }
+ load_symbols32(&ehdr, fd);
+ }
+
+ close(fd);
+ return retval;
+ error:
+ close(fd);
+ return -1;
+}
+
+
static void io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#if 0
@@ -183,84 +314,101 @@
&io_readl,
};
+static const int ide_iobase[2] = { 0x1f0, 0x170 };
+static const int ide_iobase2[2] = { 0x3f6, 0x376 };
+static const int ide_irq[2] = { 14, 15 };
+
void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename)
{
char buf[1024];
- target_ulong kernel_base, kernel_size, initrd_base, initrd_size;
+ elf_word entry = 0;
unsigned long bios_offset;
int io_memory;
- int linux_boot;
int ret;
CPUState *env;
-
- printf("%s: start\n", __func__);
- linux_boot = (kernel_filename != NULL);
+ int i;
env = cpu_init();
register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
+
+ /* Try to load a BIOS image. If this fails, we continue regardless,
+ but initialize the hardware ourselves. When a kernel gets
+ preloaded we also initialize the hardware, since the BIOS wasn't
+ run. */
bios_offset = ram_size + vga_ram_size;
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
printf("%s: load BIOS '%s' size %d\n", __func__, buf, BIOS_SIZE);
ret = load_image(buf, phys_ram_base + bios_offset);
- if (ret != BIOS_SIZE) {
- fprintf(stderr, "qemu: could not load MIPS bios '%s'\n", buf);
- exit(1);
+ if (ret == BIOS_SIZE) {
+ cpu_register_physical_memory((uint32_t)(0x1fc00000),
+ BIOS_SIZE, bios_offset | IO_MEM_ROM);
+ env->PC = 0xBFC00000;
+ if (!kernel_filename)
+ return;
+ } else {
+ /* not fatal */
+ fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
+ buf);
}
- cpu_register_physical_memory((uint32_t)(0x1fc00000),
- BIOS_SIZE, bios_offset | IO_MEM_ROM);
-#if 0
- memcpy(phys_ram_base + 0x10000, phys_ram_base + bios_offset, BIOS_SIZE);
- env->PC = 0x80010004;
-#else
- env->PC = 0xBFC00004;
-#endif
- if (linux_boot) {
- kernel_base = KERNEL_LOAD_ADDR;
- /* now we can load the kernel */
- kernel_size = load_image(kernel_filename,
- phys_ram_base + (kernel_base - 0x80000000));
- if (kernel_size == (target_ulong) -1) {
+
+ if (kernel_filename) {
+ /* Prepare the bootsector if a disk image was specified via -hda. */
+ if (bs_table[0]) {
+ uint8_t bootsect[512];
+ uint8_t old_bootsect[512];
+
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, LINUX_BOOT_FILENAME);
+ ret = load_image(buf, bootsect);
+ if (ret != sizeof(bootsect)) {
+ fprintf(stderr, "qemu: could not load linux boot sector '%s'\n",
+ buf);
+ exit(1);
+ }
+
+ if (bdrv_read(bs_table[0], 0, old_bootsect, 1) >= 0) {
+ /* copy the MSDOS partition table */
+ memcpy(bootsect + 0x1be, old_bootsect + 0x1be, 0x40);
+ }
+
+ bdrv_set_boot_sector(bs_table[0], bootsect, sizeof(bootsect));
+ }
+
+ if (load_mips_kernel_elf(kernel_filename, &entry)) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
- }
+ }
+ env->PC = entry;
+
/* load initrd */
if (initrd_filename) {
- initrd_base = INITRD_LOAD_ADDR;
- initrd_size = load_image(initrd_filename,
- phys_ram_base + initrd_base);
- if (initrd_size == (target_ulong) -1) {
+ if (load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR)
+ == (target_ulong) -1) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
initrd_filename);
exit(1);
}
- } else {
- initrd_base = 0;
- initrd_size = 0;
}
- env->PC = KERNEL_LOAD_ADDR;
+
/* Store command line. */
strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
/* FIXME: little endian support */
*(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
*(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
- } else {
- kernel_base = 0;
- kernel_size = 0;
- initrd_base = 0;
- initrd_size = 0;
}
/* Init internal devices */
cpu_mips_clock_init(env);
cpu_mips_irqctrl_init();
+ rtc_state = rtc_init(0x70, 8);
+
/* Register 64 KB of ISA IO space at 0x14000000 */
io_memory = cpu_register_io_memory(0, io_read, io_write, NULL);
cpu_register_physical_memory(0x14000000, 0x00010000, io_memory);
@@ -268,6 +416,7 @@
isa_pic = pic_init(pic_irq_request, env);
pit = pit_init(0x40, 0);
+
serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
vga_initialize(NULL, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size, 0, 0);
@@ -281,6 +430,16 @@
exit (1);
}
}
+
+ for(i = 0; i < 2; i++)
+ isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+ bs_table[2 * i], bs_table[2 * i + 1]);
+
+ kbd_init();
+ DMA_init(1);
+
+ cmos_init(ram_size, boot_device, bs_table);
+
}
QEMUMachine mips_machine = {
next prev parent reply other threads:[~2006-03-06 19:34 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-02-21 19:11 [Qemu-devel] [PATCH] Add more devices for MIPS system emulation Thiemo Seufer
2006-02-22 15:28 ` Paul Brook
2006-02-22 17:35 ` Thiemo Seufer
2006-02-23 19:24 ` Paul Brook
2006-02-23 21:37 ` Thiemo Seufer
2006-02-23 21:44 ` Paul Brook
2006-03-06 14:50 ` Thiemo Seufer [this message]
2006-03-11 21:25 ` Paul Brook
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20060306145044.GB27785@networkno.de \
--to=ths@networkno.de \
--cc=paul@codesourcery.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.