Patchwork [prep,for-1.5,v2] prep: Add ELF support for -bios

login
register
mail settings
Submitter Andreas Färber
Date May 5, 2013, 5:45 p.m.
Message ID <1367775900-29706-1-git-send-email-andreas.faerber@web.de>
Download mbox | patch
Permalink /patch/241522/
State New
Headers show

Comments

Andreas Färber - May 5, 2013, 5:45 p.m.
This prepares for switching from OpenHack'Ware to OpenBIOS.

While touching the error handling code, switch from aborting hw_error()
to fprintf()+exit() and suppress failing without -bios for qtest.

Signed-off-by: Andreas Färber <andreas.faerber@web.de>
---
 hw/ppc/prep.c | 31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)
Alexander Graf - May 5, 2013, 6:40 p.m.
Am 05.05.2013 um 19:45 schrieb Andreas Färber <andreas.faerber@web.de>:

> This prepares for switching from OpenHack'Ware to OpenBIOS.
> 
> While touching the error handling code, switch from aborting hw_error()
> to fprintf()+exit() and suppress failing without -bios for qtest.
> 
> Signed-off-by: Andreas Färber <andreas.faerber@web.de>

Acked-by: Alexander Graf <agraf@suse.de>

Alex

> ---
> hw/ppc/prep.c | 31 ++++++++++++++++++++++---------
> 1 file changed, 22 insertions(+), 9 deletions(-)
> 
> diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
> index 2ad5b41..afa62d7 100644
> --- a/hw/ppc/prep.c
> +++ b/hw/ppc/prep.c
> @@ -40,7 +40,9 @@
> #include "hw/isa/pc87312.h"
> #include "sysemu/blockdev.h"
> #include "sysemu/arch_init.h"
> +#include "sysemu/qtest.h"
> #include "exec/address-spaces.h"
> +#include "elf.h"
> 
> //#define HARD_DEBUG_PPC_IO
> //#define DEBUG_PPC_IO
> @@ -505,18 +507,29 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
>         bios_name = BIOS_FILENAME;
>     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
>     if (filename) {
> -        bios_size = get_image_size(filename);
> +        bios_size = load_elf(filename, NULL, NULL, NULL,
> +                             NULL, NULL, 1, ELF_MACHINE, 0);
> +        if (bios_size < 0) {
> +            bios_size = get_image_size(filename);
> +            if (bios_size > 0 && bios_size <= BIOS_SIZE) {
> +                hwaddr bios_addr;
> +                bios_size = (bios_size + 0xfff) & ~0xfff;
> +                bios_addr = (uint32_t)(-bios_size);
> +                bios_size = load_image_targphys(filename, bios_addr, bios_size);
> +            }
> +            if (bios_size > BIOS_SIZE) {
> +                fprintf(stderr, "qemu: PReP bios '%s' is too large (0x%x)\n",
> +                        bios_name, bios_size);
> +                exit(1);
> +            }
> +        }
>     } else {
>         bios_size = -1;
>     }
> -    if (bios_size > 0 && bios_size <= BIOS_SIZE) {
> -        hwaddr bios_addr;
> -        bios_size = (bios_size + 0xfff) & ~0xfff;
> -        bios_addr = (uint32_t)(-bios_size);
> -        bios_size = load_image_targphys(filename, bios_addr, bios_size);
> -    }
> -    if (bios_size < 0 || bios_size > BIOS_SIZE) {
> -        hw_error("qemu: could not load PPC PREP bios '%s'\n", bios_name);
> +    if (bios_size < 0 && !qtest_enabled()) {
> +        fprintf(stderr, "qemu: could not load PPC PReP bios '%s'\n",
> +                bios_name);
> +        exit(1);
>     }
>     if (filename) {
>         g_free(filename);
> -- 
> 1.8.1.4
>
Andreas Färber - May 5, 2013, 7 p.m.
Am 05.05.2013 20:40, schrieb Alexander Graf:
> 
> 
> Am 05.05.2013 um 19:45 schrieb Andreas Färber <andreas.faerber@web.de>:
> 
>> This prepares for switching from OpenHack'Ware to OpenBIOS.
>>
>> While touching the error handling code, switch from aborting hw_error()
>> to fprintf()+exit() and suppress failing without -bios for qtest.
>>
>> Signed-off-by: Andreas Färber <andreas.faerber@web.de>
> 
> Acked-by: Alexander Graf <agraf@suse.de>

Thanks, applied to prep-up:
http://repo.or.cz/w/qemu/afaerber.git/shortlog/refs/heads/prep-up

Sorry, forgot the changelog:
* error handling was split up as suggested by Alex,
* missing exit(1) calls were added and
* (partial) qtest support was added.

Andreas
Fabien Chouteau - May 6, 2013, 7:55 a.m.
On 05/05/2013 09:00 PM, Andreas Färber wrote:
> Am 05.05.2013 20:40, schrieb Alexander Graf:
>>
>>
>> Am 05.05.2013 um 19:45 schrieb Andreas Färber <andreas.faerber@web.de>:
>>
>>> This prepares for switching from OpenHack'Ware to OpenBIOS.
>>>
>>> While touching the error handling code, switch from aborting hw_error()
>>> to fprintf()+exit() and suppress failing without -bios for qtest.
>>>
>>> Signed-off-by: Andreas Färber <andreas.faerber@web.de>
>>
>> Acked-by: Alexander Graf <agraf@suse.de>
> 
> Thanks, applied to prep-up:
> http://repo.or.cz/w/qemu/afaerber.git/shortlog/refs/heads/prep-up
> 
> Sorry, forgot the changelog:
> * error handling was split up as suggested by Alex,
> * missing exit(1) calls were added and

BTW, why do you use fprintf()+exit() instead of hw_error()?
Andreas Färber - May 6, 2013, 4:10 p.m.
Am 06.05.2013 09:55, schrieb Fabien Chouteau:
> On 05/05/2013 09:00 PM, Andreas Färber wrote:
>> Am 05.05.2013 20:40, schrieb Alexander Graf:
>>>
>>>
>>> Am 05.05.2013 um 19:45 schrieb Andreas Färber <andreas.faerber@web.de>:
>>>
>>>> This prepares for switching from OpenHack'Ware to OpenBIOS.
>>>>
>>>> While touching the error handling code, switch from aborting hw_error()
>>>> to fprintf()+exit() and suppress failing without -bios for qtest.
>>>>
>>>> Signed-off-by: Andreas Färber <andreas.faerber@web.de>
>>>
>>> Acked-by: Alexander Graf <agraf@suse.de>
>>
>> Thanks, applied to prep-up:
>> http://repo.or.cz/w/qemu/afaerber.git/shortlog/refs/heads/prep-up
>>
>> Sorry, forgot the changelog:
>> * error handling was split up as suggested by Alex,
>> * missing exit(1) calls were added and
> 
> BTW, why do you use fprintf()+exit() instead of hw_error()?

That error is triggered by the user specifying a wrong -bios argument,
so we should fail gracefully (similar discussion about -m a while back)
and the CPU states are not so interesting at that point.

Andreas
Julio Guerra - July 2, 2013, 1:39 p.m.
2013/5/5 Andreas Färber <andreas.faerber@web.de>:
> This prepares for switching from OpenHack'Ware to OpenBIOS.
>
> While touching the error handling code, switch from aborting hw_error()
> to fprintf()+exit() and suppress failing without -bios for qtest.
>

I still can't run bare-metal elf programs from -bios option. Where is
the instruction pointer set to the elf program entry address ?

E.g. trying to run a bare-metal infinite loop linked at 0x4XXX. adresses :
./qemu-system-ppc -M prep -m 256M -bios loop.elf -nographic -d in_asm
QEMU 1.5.50 monitor - type 'help' for more information
(qemu)
invalid/unsupported opcode: 00 - 00 - 00 (00000000) fffffffc 0
IN:
0xfffffffc:  .long 0x0

invalid/unsupported opcode: 00 - 00 - 00 (00000000) fff00700 0
IN:
0xfff00700:  .long 0x0

--
Julio Guerra
Andreas Färber - July 2, 2013, 1:53 p.m.
Am 02.07.2013 15:39, schrieb Julio Guerra:
> 2013/5/5 Andreas Färber <andreas.faerber@web.de>:
>> This prepares for switching from OpenHack'Ware to OpenBIOS.
>>
>> While touching the error handling code, switch from aborting hw_error()
>> to fprintf()+exit() and suppress failing without -bios for qtest.
>>
> 
> I still can't run bare-metal elf programs from -bios option. Where is
> the instruction pointer set to the elf program entry address ?

By definition, bare-metal programs run on real hardware and thus need to
have their entry point where the hardware expects it - either 0xfffffffc
or 0xfff00100 depending on -cpu model.

Note that when you run a -bios, no other firmware is loaded before, so
you need to populate the exception vectors yourself, such as 0xfff00700
below. You can peek at how OpenBIOS handles this for an example.

Magically changing the CPU's reset vector would be a clear deviation
from the hardware we're modelling. But if you spot differences between
real hardware and QEMU please do report that.

If you want to load a kernel on top of firmware (i.e., not bare-metal),
use -kernel instead.
On PReP that currently uses OpenHack'Ware; my latest attempts to switch
to OpenBIOS exited unexpectedly from the Forth runtime - any help with
debugging appreciated.

Andreas

> E.g. trying to run a bare-metal infinite loop linked at 0x4XXX. adresses :
> ./qemu-system-ppc -M prep -m 256M -bios loop.elf -nographic -d in_asm
> QEMU 1.5.50 monitor - type 'help' for more information
> (qemu)
> invalid/unsupported opcode: 00 - 00 - 00 (00000000) fffffffc 0
> IN:
> 0xfffffffc:  .long 0x0
> 
> invalid/unsupported opcode: 00 - 00 - 00 (00000000) fff00700 0
> IN:
> 0xfff00700:  .long 0x0
> 
> --
> Julio Guerra
>

Patch

diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 2ad5b41..afa62d7 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -40,7 +40,9 @@ 
 #include "hw/isa/pc87312.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/arch_init.h"
+#include "sysemu/qtest.h"
 #include "exec/address-spaces.h"
+#include "elf.h"
 
 //#define HARD_DEBUG_PPC_IO
 //#define DEBUG_PPC_IO
@@ -505,18 +507,29 @@  static void ppc_prep_init(QEMUMachineInitArgs *args)
         bios_name = BIOS_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
     if (filename) {
-        bios_size = get_image_size(filename);
+        bios_size = load_elf(filename, NULL, NULL, NULL,
+                             NULL, NULL, 1, ELF_MACHINE, 0);
+        if (bios_size < 0) {
+            bios_size = get_image_size(filename);
+            if (bios_size > 0 && bios_size <= BIOS_SIZE) {
+                hwaddr bios_addr;
+                bios_size = (bios_size + 0xfff) & ~0xfff;
+                bios_addr = (uint32_t)(-bios_size);
+                bios_size = load_image_targphys(filename, bios_addr, bios_size);
+            }
+            if (bios_size > BIOS_SIZE) {
+                fprintf(stderr, "qemu: PReP bios '%s' is too large (0x%x)\n",
+                        bios_name, bios_size);
+                exit(1);
+            }
+        }
     } else {
         bios_size = -1;
     }
-    if (bios_size > 0 && bios_size <= BIOS_SIZE) {
-        hwaddr bios_addr;
-        bios_size = (bios_size + 0xfff) & ~0xfff;
-        bios_addr = (uint32_t)(-bios_size);
-        bios_size = load_image_targphys(filename, bios_addr, bios_size);
-    }
-    if (bios_size < 0 || bios_size > BIOS_SIZE) {
-        hw_error("qemu: could not load PPC PREP bios '%s'\n", bios_name);
+    if (bios_size < 0 && !qtest_enabled()) {
+        fprintf(stderr, "qemu: could not load PPC PReP bios '%s'\n",
+                bios_name);
+        exit(1);
     }
     if (filename) {
         g_free(filename);