diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2020-07-11 19:27:59 +0100 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2020-07-11 19:27:59 +0100 |
| commit | d34498309cff7560ac90c422c56e3137e6a64b19 (patch) | |
| tree | 0a5207cc1a1a637b5abb3db997b503c1ce9f5375 /hw/avr/boot.c | |
| parent | 2033cc6efa98b831d7839e367aa7d5aa74d0750f (diff) | |
| parent | 19b293472f1514b5424ef4d9b092e02bd9b106c2 (diff) | |
| download | focaccia-qemu-d34498309cff7560ac90c422c56e3137e6a64b19.tar.gz focaccia-qemu-d34498309cff7560ac90c422c56e3137e6a64b19.zip | |
Merge remote-tracking branch 'remotes/philmd-gitlab/tags/avr-port-20200711' into staging
8bit AVR port from Michael Rolnik. Michael started to work on the AVR port few years ago [*] and kept improving the code over various series. List of people who help him (in chronological order): - Richard Henderson - Sarah Harris and Edward Robbins - Philippe Mathieu-Daudé and Aleksandar Markovic - Pavel Dovgalyuk - Thomas Huth [*] The oldest contribution I could find on the list is from 2016: https://lists.nongnu.org/archive/html/qemu-devel/2016-06/msg02985.html Tests included: $ avocado --show=app run -t arch:avr tests/acceptance/ Fetching asset from tests/acceptance/machine_avr6.py:AVR6Machine.test_freertos (1/1) tests/acceptance/machine_avr6.py:AVR6Machine.test_freertos: PASS (2.13 s) RESULTS : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0 JOB TIME : 2.35 s $ make check-qtest-avr TEST check-qtest-avr: tests/qtest/boot-serial-test TEST check-qtest-avr: tests/qtest/cdrom-test TEST check-qtest-avr: tests/qtest/device-introspect-test TEST check-qtest-avr: tests/qtest/machine-none-test TEST check-qtest-avr: tests/qtest/qmp-test TEST check-qtest-avr: tests/qtest/qmp-cmd-test TEST check-qtest-avr: tests/qtest/qom-test TEST check-qtest-avr: tests/qtest/test-hmp TEST check-qtest-avr: tests/qtest/qos-test CI results: . https://cirrus-ci.com/build/5697049146425344 . https://gitlab.com/philmd/qemu/-/pipelines/165328058 . https://travis-ci.org/github/philmd/qemu/builds/705817933 . https://app.shippable.com/github/philmd/qemu/runs/822/summary/console # gpg: Signature made Sat 11 Jul 2020 10:03:11 BST # gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE # gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full] # Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE * remotes/philmd-gitlab/tags/avr-port-20200711: (32 commits) target/avr/disas: Fix store instructions display order target/avr/cpu: Fix $PC displayed address target/avr/cpu: Drop tlb_flush() in avr_cpu_reset() target/avr: Add section into QEMU documentation tests/acceptance: Test the Arduino MEGA2560 board tests/boot-serial: Test some Arduino boards (AVR based) hw/avr: Add limited support for some Arduino boards hw/avr: Add some ATmega microcontrollers hw/avr: Add support for loading ELF/raw binaries hw/misc: avr: Add limited support for power reduction device hw/timer: avr: Add limited support for 16-bit timer peripheral hw/char: avr: Add limited support for USART peripheral tests/machine-none: Add AVR support target/avr: Register AVR support with the rest of QEMU target/avr: Add support for disassembling via option '-d in_asm' target/avr: Initialize TCG register variables target/avr: Add instruction translation - CPU main translation function target/avr: Add instruction translation - MCU Control Instructions target/avr: Add instruction translation - Bit and Bit-test Instructions target/avr: Add instruction translation - Data Transfer Instructions ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/avr/boot.c')
| -rw-r--r-- | hw/avr/boot.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/hw/avr/boot.c b/hw/avr/boot.c new file mode 100644 index 0000000000..6fbcde4061 --- /dev/null +++ b/hw/avr/boot.c @@ -0,0 +1,115 @@ +/* + * AVR loader helpers + * + * Copyright (c) 2019-2020 Philippe Mathieu-Daudé + * + * This work is licensed under the terms of the GNU GPLv2 or later. + * See the COPYING file in the top-level directory. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "hw/loader.h" +#include "elf.h" +#include "boot.h" +#include "qemu/error-report.h" + +static const char *avr_elf_e_flags_to_cpu_type(uint32_t flags) +{ + switch (flags & EF_AVR_MACH) { + case bfd_mach_avr1: + return AVR_CPU_TYPE_NAME("avr1"); + case bfd_mach_avr2: + return AVR_CPU_TYPE_NAME("avr2"); + case bfd_mach_avr25: + return AVR_CPU_TYPE_NAME("avr25"); + case bfd_mach_avr3: + return AVR_CPU_TYPE_NAME("avr3"); + case bfd_mach_avr31: + return AVR_CPU_TYPE_NAME("avr31"); + case bfd_mach_avr35: + return AVR_CPU_TYPE_NAME("avr35"); + case bfd_mach_avr4: + return AVR_CPU_TYPE_NAME("avr4"); + case bfd_mach_avr5: + return AVR_CPU_TYPE_NAME("avr5"); + case bfd_mach_avr51: + return AVR_CPU_TYPE_NAME("avr51"); + case bfd_mach_avr6: + return AVR_CPU_TYPE_NAME("avr6"); + case bfd_mach_avrtiny: + return AVR_CPU_TYPE_NAME("avrtiny"); + case bfd_mach_avrxmega2: + return AVR_CPU_TYPE_NAME("xmega2"); + case bfd_mach_avrxmega3: + return AVR_CPU_TYPE_NAME("xmega3"); + case bfd_mach_avrxmega4: + return AVR_CPU_TYPE_NAME("xmega4"); + case bfd_mach_avrxmega5: + return AVR_CPU_TYPE_NAME("xmega5"); + case bfd_mach_avrxmega6: + return AVR_CPU_TYPE_NAME("xmega6"); + case bfd_mach_avrxmega7: + return AVR_CPU_TYPE_NAME("xmega7"); + default: + return NULL; + } +} + +bool avr_load_firmware(AVRCPU *cpu, MachineState *ms, + MemoryRegion *program_mr, const char *firmware) +{ + const char *filename; + int bytes_loaded; + uint64_t entry; + uint32_t e_flags; + + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware); + if (filename == NULL) { + error_report("Unable to find %s", firmware); + return false; + } + + bytes_loaded = load_elf_ram_sym(filename, + NULL, NULL, NULL, + &entry, NULL, NULL, + &e_flags, 0, EM_AVR, 0, 0, + NULL, true, NULL); + if (bytes_loaded >= 0) { + /* If ELF file is provided, determine CPU type reading ELF e_flags. */ + const char *elf_cpu = avr_elf_e_flags_to_cpu_type(e_flags); + const char *mcu_cpu_type = object_get_typename(OBJECT(cpu)); + int cpu_len = strlen(mcu_cpu_type) - strlen(AVR_CPU_TYPE_SUFFIX); + + if (entry) { + error_report("BIOS entry_point must be 0x0000 " + "(ELF image '%s' has entry_point 0x%04" PRIx64 ")", + firmware, entry); + return false; + } + if (!elf_cpu) { + warn_report("Could not determine CPU type for ELF image '%s', " + "assuming '%.*s' CPU", + firmware, cpu_len, mcu_cpu_type); + return true; + } + if (strcmp(elf_cpu, mcu_cpu_type)) { + error_report("Current machine: %s with '%.*s' CPU", + MACHINE_GET_CLASS(ms)->desc, cpu_len, mcu_cpu_type); + error_report("ELF image '%s' is for '%.*s' CPU", + firmware, + (int)(strlen(elf_cpu) - strlen(AVR_CPU_TYPE_SUFFIX)), + elf_cpu); + return false; + } + } else { + bytes_loaded = load_image_mr(filename, program_mr); + } + if (bytes_loaded < 0) { + error_report("Unable to load firmware image %s as ELF or raw binary", + firmware); + return false; + } + return true; +} |