From 424f9f67964b01ce39c3cedfc2e189770c11a8bc Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 5 May 2022 17:23:49 +0200 Subject: [PATCH] doc: how to use QEMU to test big-endian build Document the process of using buildroot to build a big-endian binary of OpenOCD and using QEMU User Mode Emulation for running the big-endian binary on a little-endian host PC. Change-Id: Ic5fe26e353a4cf69e57af3c23ae7fa4b25347b2b Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6968 Tested-by: jenkins Reviewed-by: Tomas Vanek --- contrib/buildroot/openocd_be_defconfig | 27 ++++ doc/manual/endianness.txt | 197 +++++++++++++++++++++++++ doc/manual/main.txt | 2 + 3 files changed, 226 insertions(+) create mode 100644 contrib/buildroot/openocd_be_defconfig create mode 100644 doc/manual/endianness.txt diff --git a/contrib/buildroot/openocd_be_defconfig b/contrib/buildroot/openocd_be_defconfig new file mode 100644 index 000000000..9752da50e --- /dev/null +++ b/contrib/buildroot/openocd_be_defconfig @@ -0,0 +1,27 @@ +BR2_armeb=y +BR2_cortex_a7=y +BR2_TOOLCHAIN_EXTERNAL=y +BR2_PACKAGE_OPENOCD=y +BR2_PACKAGE_OPENOCD_FTDI=y +BR2_PACKAGE_OPENOCD_STLINK=y +BR2_PACKAGE_OPENOCD_TI_ICDI=y +BR2_PACKAGE_OPENOCD_ULINK=y +BR2_PACKAGE_OPENOCD_UBLASTER2=y +BR2_PACKAGE_OPENOCD_JLINK=y +BR2_PACKAGE_OPENOCD_OSDBM=y +BR2_PACKAGE_OPENOCD_OPENDOUS=y +BR2_PACKAGE_OPENOCD_AICE=y +BR2_PACKAGE_OPENOCD_VSLLINK=y +BR2_PACKAGE_OPENOCD_USBPROG=y +BR2_PACKAGE_OPENOCD_RLINK=y +BR2_PACKAGE_OPENOCD_ARMEW=y +BR2_PACKAGE_OPENOCD_XDS110=y +BR2_PACKAGE_OPENOCD_PARPORT=y +BR2_PACKAGE_OPENOCD_VPI=y +BR2_PACKAGE_OPENOCD_UBLASTER=y +BR2_PACKAGE_OPENOCD_AMTJT=y +BR2_PACKAGE_OPENOCD_GW16012=y +BR2_PACKAGE_OPENOCD_PRESTO=y +BR2_PACKAGE_OPENOCD_OPENJTAG=y +BR2_PACKAGE_OPENOCD_BUSPIRATE=y +BR2_PACKAGE_OPENOCD_SYSFS=y diff --git a/doc/manual/endianness.txt b/doc/manual/endianness.txt new file mode 100644 index 000000000..bba2116b5 --- /dev/null +++ b/doc/manual/endianness.txt @@ -0,0 +1,197 @@ +/** @page endianness About endianness + +OpenOCD has to potentially deal with different endianness between: +- the host PC endianness; +- the data endianness during communication between host and adapter; +- the target CPU endianness. + +The whole OpenOCD code should be written to handle any endianness +mismatch and should run on either little and big endian hosts. + +Big-endian host PC are becoming less and less common since Apple™ has +switched away from big-endian PowerPC™ in favor of little-endian intel +X86™. + +The lack of commercial big-endian hosts makes hard testing OpenOCD correctness +on big-endian hosts. Running OpenOCD on low-cost commercial routers based on +big-endian MIPS is possible, but it's tricky to properly setup the system and +the cross-compiling environment. + +In next sections there are two example on how to compile and test OpenOCD in an +emulated big-endian environment. + + +@section endianness_helpers OpenOCD API for handling endianness + +Use the following OpenOCD API to handle endianness conversions: +- host endianness to/from little endian: + - le_to_h_u64(), le_to_h_u32(), le_to_h_u16(); + - h_u64_to_le(), h_u32_to_le(), h_u16_to_le(); + - buf_get_u32(), buf_get_u64(); + - buf_set_u32(), buf_set_u64(); +- host endianness to/from big endian: + - be_to_h_u64(), be_to_h_u32(), be_to_h_u16(); + - h_u64_to_be(), h_u32_to_be(), h_u16_to_be(); +- host endianness to/from target endianness: + - target_read_u64(), target_read_u32(), target_read_u16(); + - target_write_u64(), target_write_u32(), target_write_u16(); + - target_write_phys_u64(), target_write_phys_u32(), target_write_phys_u16(); + - target_buffer_get_u64(), target_buffer_get_u32(), target_buffer_get_u24(), target_buffer_get_u16(); + - target_buffer_set_u64(), target_buffer_set_u32(), target_buffer_set_u24(), target_buffer_set_u16(); +- byte swap: + - buf_bswap32(), buf_bswap16(). + + +@section endianness_docker Use dockers to run different endianness + + +Docker can run a full Linux image that includes the toolchain through QEMU +emulator. +By selecting a big-endian image, it's possible to compile and execute OpenOCD +in big-endian. +There are, so far, not many options for big-endian images; s390x is one of the +few available. + +To be expanded. + +User should: +- install docker; +- download the big-endian image; +- run the image in docker; +- download, in the image, the OpenOCD code to test; +- recompile OpenOCD code in the image; +- run OpenOCD binary in the image. + +From https://github.com/multiarch/qemu-user-static + + @code{.unparsed} + docker run --rm -t s390x/ubuntu bash + @endcode + + +@section endianness_qemu Use buildroot and QEMU to run different endianness + +QEMU User Mode Emulation is an efficient method to launch, on host's CPU, +applications compiled for another CPU and/or for different endianness. +It works either on Linux and BSD. More info available on +https://www.qemu.org/docs/master/user/index.html + +With QEMU User Mode Emulation is thus possible running, on a commonly available +little-endian X86 Linux host, OpenOCD compiled for a big-endian host. + +The following example will show how to use buildroot to: +- build big-endian toolchain and libraries; +- compile OpenOCD for big-endian; +- run the big-endian OpenOCD on little-endian Linux PC. + +The example will use ARM Cortex-A7 big-endian only because I personally feel +comfortable reading ARM assembly during debug. User can select other CPU +architectures, as this does not impact the result. + +A similar method can be used to test OpenOCD compiled for 32 vs 64 bit host. + +@note +- the version of autotools locally installer in your Linux host can be + incompatible with the version of autotools used by buildroot. This can cause + the build to fail if buildroot has to run its autotools on a partially + configured OpenOCD folder. Use either a clean copy of OpenOCD code in 2., or + run "./bootstrap" in OpenOCD folder to prevent buildroot from using its own + autotools; +- the configuration tool in 4. and 5. matches the version of OpenOCD used by + buildroot. Some new driver could be not listed in. OpenOCD will build every + driver that is not disabled and with satisfied dependencies. If the driver + you plan to use is not listed, try a first build and check OpenOCD with + command "adapter list", then try to hack the buildroot files Config.in and + openocd.mk in folder package/openocd/ and use "make openocd-reconfigure" to + rerun the build starting with configuration; +- using pre-built toolchains, you need 2GB of disk space for buildroot build. + To also rebuild the toolchains you will need ~5GB and much longer time for + the first build (it takes ~2 hour on my crap 10+ years old laptop); +- you need to install few tools for buildroot dependency, listed in + https://buildroot.org/downloads/manual/manual.html#requirement ; +- you need to install qemu-armeb. On Arch Linux it's in package qemu-arch-extra; + on Ubuntu/debian it's packaged in qemu-user. + Buildroot can also be configured to build qemu for the host, if you prefer, + by enabling BR2_PACKAGE_HOST_QEMU_LINUX_USER_MODE, but this takes longer + compile time; +- don't use qemu-system-arm, as it emulates a complete system and requires a + fully bootable ARM image; +- while QEMU User Mode Emulation is available for both Linux and BSD, buildroot + only builds binaries for Linux target. This example can only be used with + Linux hosts emulating the Linux target. + + +Steps to run big-endian OpenOCD on little-endian host Linux PC: + +1. Get buildroot source. Today's latest version is "2022.02": + @code{.unparsed} + wget https://buildroot.org/downloads/buildroot-2022.02.tar.xz + tar xf buildroot-2022.02.tar.xz + cd buildroot-2022.02 + @endcode + +2. Override the source repo for OpenOCD in order to build your own code version + in place of the default OpenOCD release version: + @code{.unparsed} + echo OPENOCD_OVERRIDE_SRCDIR=/home/me/openocd.git >> local.mk + @endcode + +3. Copy default config for OpenOCD big-endian. This used: + - ARM Cortex-A7 big-endian target, + - external Linaro armeb toolchain (to speed up first build), + - OpenOCD all configure options enabled. + + @code{.unparsed} + cp $OPENOCD_OVERRIDE_SRCDIR/contrib/buildroot/openocd_be_defconfig configs/ + @endcode + +4. Configure buildroot with default config for OpenOCD big-endian: + @code{.unparsed} + make openocd_be_defconfig + @endcode + +5. Optional, change buildroot configuration: + @code{.unparsed} + make menuconfig + @endcode + These are the options selected with default config for OpenOCD big-endian: + @code{.unparsed} + Target options ---> + Target Architecture ---> + ARM (big endian) + Target Architecture Variant ---> + cortex-A7 + Toolchain ---> + Toolchain type ---> + External toolchain + Toolchain ---> + Linaro armeb 2018.05 + Toolchain origin ---> + Toolchain to be downloaded and installed + Target packages ---> + Hardware handling ---> + openocd + All adapters selected + @endcode + Save and exit + +6. Build (and take a long coffee break ...): + @code{.unparsed} + make openocd + @endcode + +7. Execute big-endian OpenOCD: + @code{.unparsed} + cd output/target + qemu-armeb -cpu cortex-a7 -L . usr/bin/openocd -s usr/share/openocd/scripts/ -f board/st_nucleo_f4.cfg + @endcode + +8. Optional, to rebuild after any source code modification in ${OPENOCD_OVERRIDE_SRCDIR}: + @code{.unparsed} + make openocd-rebuild + @endcode + + */ +/** @file +This file contains the @ref endianness page. + */ diff --git a/doc/manual/main.txt b/doc/manual/main.txt index 14c64c2e7..c28fbe228 100644 --- a/doc/manual/main.txt +++ b/doc/manual/main.txt @@ -19,6 +19,8 @@ check the mailing list archives to find the status of your feature (or bug). - The @subpage bugs page contains the content of the BUGS file, which provides instructions for submitting bug reports to the maintainers. - The @subpage releases page describes the project's release process. +- The @subpage endianness provides hints about writing and testing + endianness independent code for OpenOCD. @ref primer provide introductory materials for new developers on various specific topics.