diff --git a/.github/workflows/docker_img.yaml b/.github/workflows/docker_img.yaml index a0fc677dfc06d4..b7d93bc49279ce 100644 --- a/.github/workflows/docker_img.yaml +++ b/.github/workflows/docker_img.yaml @@ -54,6 +54,7 @@ jobs: - "-telink" - "-ti" - "-tizen" + - "-tizen-qemu" - "-openiotsdk" # NOTE: vscode image consumes ~52 GB disk space but GitHub-hosted runners provide ~10 GB free disk space(https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources) #- "-vscode" diff --git a/integrations/docker/images/chip-build-tizen-qemu/Dockerfile b/integrations/docker/images/chip-build-tizen-qemu/Dockerfile new file mode 100644 index 00000000000000..8d2c3abb2ecbe1 --- /dev/null +++ b/integrations/docker/images/chip-build-tizen-qemu/Dockerfile @@ -0,0 +1,180 @@ +ARG VERSION=latest +FROM connectedhomeip/chip-build-tizen:${VERSION} + +ENV TIZEN_IOT_QEMU_KERNEL $TIZEN_SDK_ROOT/iot-qemu-virt-zImage +ENV TIZEN_IOT_IMAGE_ROOT $TIZEN_SDK_ROOT/iot-rootfs.img +ENV TIZEN_IOT_IMAGE_DATA $TIZEN_SDK_ROOT/iot-sysdata.img + +# ------------------------------------------------------------------------------ +# Switch to the root user so we could install things +USER root + +# ------------------------------------------------------------------------------ +# Install QEMU and build dependencies +RUN set -x \ + && apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -fy --no-install-recommends \ + bc \ + genisoimage \ + qemu-system-arm \ + # Cleanup + && apt-get clean \ + && rm -rf /var/lib/apt/lists \ + && : # last line + +# It seems that Linux kernel does not support overlay FS with SMACK enabled. In +# order not to disable SMACK LSM support completely (it could break some tools +# in Tizen ecosystem) we will add "permissive" mode to SMACK. +COPY files/0001-smack-add-permissive-mode.patch $TIZEN_SDK_ROOT/files/ + +# ------------------------------------------------------------------------------ +# Build Tizen kernel +RUN set -x \ + && mkdir -p /tmp/workdir && cd /tmp/workdir \ + # Download Linux rpi4 kernel + && wget --progress=dot:giga -r -nd --no-parent -A 'rpi4-linux-kernel-*.src.rpm' \ + http://download.tizen.org/snapshots/tizen/$TIZEN_VERSION-unified/latest/repos/standard/source/ \ + # Prepare kernel source (Linux kernel + Tizen patchset) + && unrpm rpi4-linux-kernel-*.src.rpm \ + && tar -xJf linux-kernel-*.tar.xz \ + && rm linux-kernel-*.tar.xz \ + && cd linux-kernel-* \ + && zcat ../*-to-*.diff.gz | patch -p1 \ + && patch -p1 < $TIZEN_SDK_ROOT/files/0001-smack-add-permissive-mode.patch \ + # Compile + && export MAKEFLAGS=-j$(nproc) \ + && export ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- \ + && make tizen_bcm2711_defconfig \ + && ./scripts/config -e ARCH_VIRT \ + && ./scripts/config -e VIRTIO_MMIO -e HW_RANDOM_VIRTIO \ + && ./scripts/config -e VIRTIO_PCI -e VIRTIO_BLK \ + && ./scripts/config -e VIRTIO_NET -e VETH \ + && ./scripts/config -e IKCONFIG -e IKCONFIG_PROC \ + && ./scripts/config -e BT_HCIVHCI -e CRYPTO_USER_API_HASH -e CRYPTO_USER_API_SKCIPHER \ + && ./scripts/config -e OVERLAY_FS -e ISO9660_FS \ + && ./scripts/config -e SECURITY_SMACK_PERMISSIVE_MODE \ + && make olddefconfig \ + && make zImage \ + && mv arch/arm/boot/zImage $TIZEN_IOT_QEMU_KERNEL \ + # Cleanup + && rm -rf /tmp/workdir \ + && : # last line + +# ------------------------------------------------------------------------------ +# Create Tizen IoT File System +RUN set -x \ + && mkdir -p /tmp/workdir && cd /tmp/workdir \ + && SYSTEMD_SYSTEM=/usr/lib/systemd/system \ + # Download Tizen images + && wget --progress=dot:giga -r -nd --no-parent -A 'tizen-*.tar.gz' \ + http://download.tizen.org/snapshots/tizen/unified/latest/images/standard/tizen-headless-armv7l/ \ + # Unpack + && tar -xzf tizen-*.tar.gz \ + && mv system-data.img $TIZEN_IOT_IMAGE_DATA \ + && mv rootfs.img $TIZEN_IOT_IMAGE_ROOT \ + # Install libguestfs and linux-image-generic required for in-place + # modifications of the rootfs image + && apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -fy --no-install-recommends libguestfs-tools linux-image-generic \ + # Add extra libraries to the root image + && guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda glob copy-in \ + $TIZEN_SDK_TOOLCHAIN/arm-tizen-linux-gnueabi/lib/libasan.so.* \ + $TIZEN_SDK_TOOLCHAIN/arm-tizen-linux-gnueabi/lib/libubsan.so.* \ + $TIZEN_SDK_SYSROOT/usr/lib/libcapi-network-thread.so.* \ + $TIZEN_SDK_SYSROOT/usr/lib/libnsd-dns-sd.so.* \ + /usr/lib/ \ + # Disable failing systemd services + && guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda glob rm $SYSTEMD_SYSTEM/deviced.service \ + && guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda glob rm $SYSTEMD_SYSTEM/mnt-inform.mount \ + && guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda glob rm $SYSTEMD_SYSTEM/murphyd.service \ + && guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda glob rm $SYSTEMD_SYSTEM/pulseaudio.service \ + # Mount Tizen system partition on /opt-ro instead of /opt + && SYSTEMD_UNIT_OPT_RO_MOUNT=$SYSTEMD_SYSTEM/opt\\x2dro.mount \ + && guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda ln-sf $SYSTEMD_UNIT_OPT_RO_MOUNT $SYSTEMD_SYSTEM/local-fs.target.requires \ + && guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda mv $SYSTEMD_SYSTEM/opt.mount $SYSTEMD_UNIT_OPT_RO_MOUNT \ + && virt-edit $TIZEN_IOT_IMAGE_ROOT -e 's#/opt#/opt-ro#g' $SYSTEMD_UNIT_OPT_RO_MOUNT \ + && virt-edit $TIZEN_IOT_IMAGE_ROOT -e 's#Options=#Options=ro,#' $SYSTEMD_UNIT_OPT_RO_MOUNT \ + && guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda mkdir /opt-ro \ + # Create /tmp/.opt-upper and /tmp/.opt-work after /tmp is mounted + && SYSTEMD_UNIT_OPT_PRE_MOUNT=$SYSTEMD_SYSTEM/opt.pre-mount.service \ + && echo -n \ + "[Unit]\n" \ + "DefaultDependencies=no\n" \ + "RequiresMountsFor=/tmp\n" \ + "[Service]\n" \ + "Type=oneshot\n" \ + "ExecStart=mkdir -p /tmp/.opt-upper /tmp/.opt-work\n" \ + "RemainAfterExit=yes\n" \ + | guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda upload - $SYSTEMD_UNIT_OPT_PRE_MOUNT \ + # Mount Tizen system partition as a tmp-based overlay + && SYSTEMD_UNIT_OPT_MOUNT=$SYSTEMD_SYSTEM/opt.mount \ + && guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda ln-sf $SYSTEMD_UNIT_OPT_MOUNT $SYSTEMD_SYSTEM/local-fs.target.requires \ + && echo -n \ + "[Unit]\nConditionPathIsMountPoint=!/opt\n" \ + "RequiresMountsFor=/opt-ro /tmp\n" \ + "Wants=opt.pre-mount.service\n" \ + "After=opt.pre-mount.service\n" \ + "[Mount]\n" \ + "What=overlay\n" \ + "Where=/opt\n" \ + "Type=overlay\n" \ + "Options=lowerdir=/opt-ro,upperdir=/tmp/.opt-upper,workdir=/tmp/.opt-work\n" \ + | guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda upload - $SYSTEMD_UNIT_OPT_MOUNT \ + # Fix SMACK label for /tmp/.opt-work/work + && SYSTEMD_UNIT_OPT_POST_MOUNT=$SYSTEMD_SYSTEM/opt.post-mount.service \ + && guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda ln-sf $SYSTEMD_UNIT_OPT_POST_MOUNT $SYSTEMD_SYSTEM/local-fs.target.requires \ + && echo -n \ + "[Unit]\n" \ + "DefaultDependencies=no\n" \ + "RequiresMountsFor=/opt\n" \ + "[Service]\n" \ + "Type=oneshot\n" \ + "ExecStart=chsmack -a * /tmp/.opt-work/work\n" \ + "RemainAfterExit=yes\n" \ + | guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda upload - $SYSTEMD_UNIT_OPT_POST_MOUNT \ + # Mount Matter ISO image on startup + && SYSTEMD_UNIT_CHIP_MOUNT=$SYSTEMD_SYSTEM/mnt-chip.mount \ + && guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda ln-sf $SYSTEMD_UNIT_CHIP_MOUNT $SYSTEMD_SYSTEM/local-fs.target.requires \ + && echo -n \ + "[Unit]\n" \ + "ConditionPathIsMountPoint=!/mnt/chip\n" \ + "[Mount]\n" \ + "What=/dev/disk/by-label/CHIP\n" \ + "Where=/mnt/chip\n" \ + "Options=nofail\n" \ + | guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda upload - $SYSTEMD_UNIT_CHIP_MOUNT \ + && guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda mkdir /mnt/chip \ + # Setup auto-login for root user + && SYSTEMD_UNIT_SERIAL_GETTY=$SYSTEMD_SYSTEM/serial-getty@.service \ + && virt-edit $TIZEN_IOT_IMAGE_ROOT -e \ + 's#^ExecStart=.*#ExecStart=-/sbin/agetty -o "-p -f root" --noclear -a root --keep-baud 115200 %I \$TERM#' $SYSTEMD_UNIT_SERIAL_GETTY \ + # Execute launcher script after root login + && echo -n \ + "[ -x /launcher.sh ] && /launcher.sh\n" \ + | guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda upload - /root/.profile \ + # Launcher script + && echo -n \ + "#!/bin/bash\n" \ + "if [[ -x /mnt/chip/runner.sh ]]; then\n" \ + " echo '### RUNNER START ###'\n" \ + " /mnt/chip/runner.sh\n" \ + " echo '### RUNNER STOP:' $?\n" \ + "else\n" \ + " read -r -t 5 -p 'Press ENTER to access root shell...' && exit || echo ' timeout.'\n" \ + "fi\n" \ + "echo 'Shutting down emulated system...'\n" \ + "echo o > /proc/sysrq-trigger\n" \ + | guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda upload - /launcher.sh \ + && guestfish --rw -a $TIZEN_IOT_IMAGE_ROOT -m /dev/sda chmod 0755 /launcher.sh \ + # Remove ALL previously installed packages + && apt-get autopurge -fy $(tail -2 /var/log/apt/history.log | grep ^Install | cut -c 10- | sed 's/([^)]*),\?//g') \ + && rm -rf /var/lib/apt/lists \ + && rm -rf /var/tmp/.guestfs-0 \ + # Cleanup + && rm -rf /tmp/workdir \ + && : # last line + +# ------------------------------------------------------------------------------ +# Switch back to the non-root user +USER $USER_NAME +WORKDIR $USER_HOME diff --git a/integrations/docker/images/chip-build-tizen-qemu/build.sh b/integrations/docker/images/chip-build-tizen-qemu/build.sh new file mode 120000 index 00000000000000..fcb4d4ee75d531 --- /dev/null +++ b/integrations/docker/images/chip-build-tizen-qemu/build.sh @@ -0,0 +1 @@ +../../build.sh \ No newline at end of file diff --git a/integrations/docker/images/chip-build-tizen-qemu/files/0001-smack-add-permissive-mode.patch b/integrations/docker/images/chip-build-tizen-qemu/files/0001-smack-add-permissive-mode.patch new file mode 100644 index 00000000000000..2328f7fae4cb05 --- /dev/null +++ b/integrations/docker/images/chip-build-tizen-qemu/files/0001-smack-add-permissive-mode.patch @@ -0,0 +1,208 @@ +From: Chanho Park +Date: Tue, 3 Jun 2014 19:54:53 +0900 +Subject: [PATCH] LOCAL / smack: add permissive mode for debugging purpose + +This patch adds smack permissive mode. + +Signed-off-by: Chanho Park +Signed-off-by: Seung-Woo Kim +[k.kozlowski: rebased on 4.1] +Signed-off-by: Krzysztof Kozlowski +[m.szyprowski: rebased on 5.4] +Signed-off-by: Marek Szyprowski +--- + security/smack/Kconfig | 8 ++++ + security/smack/smack.h | 9 +++++ + security/smack/smack_access.c | 12 ++++++ + security/smack/smack_lsm.c | 11 ++++++ + security/smack/smackfs.c | 72 +++++++++++++++++++++++++++++++++++ + 5 files changed, 112 insertions(+) + +diff --git a/security/smack/Kconfig b/security/smack/Kconfig +index 5a8dfad469c3..39ded0b9bf38 100644 +--- a/security/smack/Kconfig ++++ b/security/smack/Kconfig +@@ -53,3 +53,11 @@ config SECURITY_SMACK_APPEND_SIGNALS + to differentiate between delivering a network packet and + delivering a signal in the Smack rules. + If you are unsure how to answer this question, answer N. ++ ++config SECURITY_SMACK_PERMISSIVE_MODE ++ bool "Enable Permissive mode for debugging purpose" ++ depends on SECURITY_SMACK ++ help ++ This selects the permissive mode of smack for debug purpose. This ++ do not block any access of the smack policy and just warn the block ++ by log message. +diff --git a/security/smack/smack.h b/security/smack/smack.h +index 335d2411abe4..9e8000c283cc 100644 +--- a/security/smack/smack.h ++++ b/security/smack/smack.h +@@ -424,6 +424,15 @@ static inline struct smack_known *smk_of_current(void) + return smk_of_task(smack_cred(current_cred())); + } + ++#ifdef CONFIG_SECURITY_SMACK_PERMISSIVE_MODE ++/* ++ * permissive mode ++ */ ++#define SMACK_PERMISSIVE_DENIED 0x0 ++#define SMACK_PERMISSIVE_ALLOWED 0x1 ++extern int permissive_mode; ++#endif ++ + /* + * logging functions + */ +diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c +index 38ac3da4e791..2b63a2643ef5 100644 +--- a/security/smack/smack_access.c ++++ b/security/smack/smack_access.c +@@ -45,6 +45,14 @@ LIST_HEAD(smack_known_list); + */ + static u32 smack_next_secid = 10; + ++/* ++ * are we running in permissive mode? ++ * can be overwritten at run-time by /smack/permissive ++ */ ++#ifdef CONFIG_SECURITY_SMACK_PERMISSIVE_MODE ++int permissive_mode = SMACK_PERMISSIVE_ALLOWED; ++#endif ++ + /* + * what events do we log + * can be overwritten at run-time by /smack/logging +@@ -200,6 +208,10 @@ int smk_access(struct smack_known *subject, struct smack_known *object, + smack_log(subject->smk_known, object->smk_known, + request, rc, a); + #endif ++#ifdef CONFIG_SECURITY_SMACK_PERMISSIVE_MODE ++ if (permissive_mode == SMACK_PERMISSIVE_ALLOWED) ++ return 0; ++#endif + + return rc; + } +diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c +index 12c0fa85d9f8..a8d2f81690e4 100644 +--- a/security/smack/smack_lsm.c ++++ b/security/smack/smack_lsm.c +@@ -4796,6 +4796,17 @@ static __init int smack_init(void) + return 0; + } + ++#ifdef CONFIG_SECURITY_SMACK_PERMISSIVE_MODE ++static int __init mode_setup(char *str) ++{ ++ unsigned long mode; ++ if (!kstrtoul(str, 10, &mode)) ++ permissive_mode = mode ? 1 : 0; ++ return 1; ++} ++__setup("permissive=", mode_setup); ++#endif ++ + /* + * Smack requires early initialization in order to label + * all processes and objects when they are created. +diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c +index c21b656b3263..fc033626085f 100644 +--- a/security/smack/smackfs.c ++++ b/security/smack/smackfs.c +@@ -59,6 +59,9 @@ enum smk_inos { + SMK_NET6ADDR = 23, /* single label IPv6 hosts */ + #endif /* CONFIG_IPV6 */ + SMK_RELABEL_SELF = 24, /* relabel possible without CAP_MAC_ADMIN */ ++#ifdef CONFIG_SECURITY_SMACK_PERMISSIVE_MODE ++ SMK_PERMISSIVE = 25, /* permissive mode */ ++#endif + }; + + /* +@@ -677,6 +680,71 @@ static const struct file_operations smk_load_ops = { + .release = seq_release, + }; + ++#ifdef CONFIG_SECURITY_SMACK_PERMISSIVE_MODE ++/** ++ * smk_read_permissive - read() for /smack/permissive ++ * @filp: file pointer, not actually used ++ * @buf: where to put the result ++ * @cn: maximum to send along ++ * @ppos: where to start ++ * ++ * Returns number of bytes read or error code, as appropriate ++ */ ++static ssize_t smk_read_permissive(struct file *filp, char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ char temp[32]; ++ ssize_t rc; ++ ++ if (*ppos != 0) ++ return 0; ++ ++ sprintf(temp, "%d\n", permissive_mode); ++ rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); ++ return rc; ++} ++ ++/** ++ * smk_write_permissive - write() for /smack/permissive ++ * @file: file pointer, not actually used ++ * @buf: where to get the data from ++ * @count: bytes sent ++ * @ppos: where to start ++ * ++ * Returns number of bytes written or error code, as appropriate ++ */ ++static ssize_t smk_write_permissive(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ char temp[32]; ++ int i; ++ ++ if (!capable(CAP_MAC_ADMIN)) ++ return -EPERM; ++ ++ if (count >= sizeof(temp) || count == 0) ++ return -EINVAL; ++ ++ if (copy_from_user(temp, buf, count) != 0) ++ return -EFAULT; ++ ++ temp[count] = '\0'; ++ ++ if (sscanf(temp, "%d", &i) != 1) ++ return -EINVAL; ++ if (i < 0 || i > 1) ++ return -EINVAL; ++ permissive_mode = i; ++ return count; ++} ++ ++static const struct file_operations smk_permissive_ops = { ++ .read = smk_read_permissive, ++ .write = smk_write_permissive, ++ .llseek = default_llseek, ++}; ++#endif /* End of CONFIG_SECURITY_SMACK_PERMISSIVE_MODE */ ++ + /** + * smk_cipso_doi - initialize the CIPSO domain + */ +@@ -2881,6 +2949,10 @@ static int smk_fill_super(struct super_block *sb, struct fs_context *fc) + [SMK_UNCONFINED] = { + "unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR}, + #endif ++#ifdef CONFIG_SECURITY_SMACK_PERMISSIVE_MODE ++ [SMK_PERMISSIVE] = { ++ "permissive", &smk_permissive_ops, S_IRUGO|S_IWUSR}, ++#endif + #if IS_ENABLED(CONFIG_IPV6) + [SMK_NET6ADDR] = { + "ipv6host", &smk_net6addr_ops, S_IRUGO|S_IWUSR}, +-- +2.17.1 + diff --git a/integrations/docker/images/chip-build-tizen-qemu/run.sh b/integrations/docker/images/chip-build-tizen-qemu/run.sh new file mode 120000 index 00000000000000..ccbd3501b330d9 --- /dev/null +++ b/integrations/docker/images/chip-build-tizen-qemu/run.sh @@ -0,0 +1 @@ +../../run.sh \ No newline at end of file diff --git a/integrations/docker/images/chip-build-tizen-qemu/version b/integrations/docker/images/chip-build-tizen-qemu/version new file mode 120000 index 00000000000000..a4280acd348e7f --- /dev/null +++ b/integrations/docker/images/chip-build-tizen-qemu/version @@ -0,0 +1 @@ +../chip-build/version \ No newline at end of file diff --git a/integrations/docker/images/chip-build-tizen/Dockerfile b/integrations/docker/images/chip-build-tizen/Dockerfile index 4aac9c1846f01a..f0334106b6cbbe 100644 --- a/integrations/docker/images/chip-build-tizen/Dockerfile +++ b/integrations/docker/images/chip-build-tizen/Dockerfile @@ -33,15 +33,13 @@ RUN set -x \ ENV TIZEN_VERSION 6.0 ENV TIZEN_SDK_ROOT /opt/tizen-sdk -COPY tizen-sdk-installer /tmp/tizen-sdk-installer +COPY tizen-sdk-installer $TIZEN_SDK_ROOT/files/installer RUN set -x \ - && bash /tmp/tizen-sdk-installer/install.sh \ + && bash $TIZEN_SDK_ROOT/files/installer/install.sh \ --tizen-sdk-path $TIZEN_SDK_ROOT \ --tizen-sdk-data-path $USER_HOME/tizen-sdk-data \ --tizen-version $TIZEN_VERSION \ --override-secret-tool \ - # Cleanup - && rm -rf /tmp/tizen-sdk-installer \ && : # last line # ------------------------------------------------------------------------------ diff --git a/integrations/docker/images/chip-build/Dockerfile b/integrations/docker/images/chip-build/Dockerfile index 8c0eaf7e486010..7b2f5c4593e3d3 100644 --- a/integrations/docker/images/chip-build/Dockerfile +++ b/integrations/docker/images/chip-build/Dockerfile @@ -95,7 +95,7 @@ RUN set -x \ && : # last line RUN set -x \ - && pip3 install \ + && pip3 install --no-cache-dir \ attrs \ click \ coloredlogs \ @@ -109,8 +109,6 @@ RUN set -x \ pygit \ PyGithub \ tabulate \ - # Cleanup - && pip3 cache purge \ && : # last line # build and install gn @@ -151,7 +149,7 @@ RUN set -x \ # Save clang-12 files, so we can restore them after build dependencies cleanup && tar -cf clang-12-files.tar $(dpkg -L libclang-common-12-dev |grep /include) /usr/lib/llvm-12/lib/libLLVM-12.so.1 \ # Cleanup build dependencies - && apt autoremove -fy clang-12 libclang-12-dev \ + && apt autopurge -fy clang-12 libclang-12-dev \ && rm -rf /var/lib/apt/lists/ \ # Restore clang-12 files && tar -xf clang-12-files.tar -C / \ @@ -168,6 +166,7 @@ RUN set -x \ ENV LD_LIBRARY_PATH_TSAN=/usr/lib/x86_64-linux-gnu-tsan RUN set -x \ && mkdir -p $LD_LIBRARY_PATH_TSAN \ + && export CCACHE_DISABLE=1 PYTHONDONTWRITEBYTECODE=1 \ && GLIB_VERSION=$(pkg-config --modversion glib-2.0) \ && git clone --depth=1 --branch=$GLIB_VERSION https://github.com/GNOME/glib.git \ && CFLAGS="-O2 -g -fsanitize=thread" meson glib/build glib \ diff --git a/integrations/docker/images/chip-build/version b/integrations/docker/images/chip-build/version index 0eb25cce600a57..d003f9e89eb144 100644 --- a/integrations/docker/images/chip-build/version +++ b/integrations/docker/images/chip-build/version @@ -1 +1 @@ -0.6.37 Version bump reason: removed ZAP from docker as CIPD now has it. +0.6.38 Version bump reason: [Tizen] Add QEMU docker image for running tests diff --git a/third_party/tizen/tizen_dev_certificate.py b/third_party/tizen/tizen_dev_certificate.py index 073561bad69ddd..9e43991fa51296 100755 --- a/third_party/tizen/tizen_dev_certificate.py +++ b/third_party/tizen/tizen_dev_certificate.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright (c) 2022 Project CHIP Authors # diff --git a/third_party/tizen/tizen_manifest_parser.py b/third_party/tizen/tizen_manifest_parser.py index 3266a4adcb858e..ddb41ed9da07e6 100755 --- a/third_party/tizen/tizen_manifest_parser.py +++ b/third_party/tizen/tizen_manifest_parser.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright (c) 2022 Project CHIP Authors # diff --git a/third_party/tizen/tizen_qemu.py b/third_party/tizen/tizen_qemu.py new file mode 100755 index 00000000000000..548cc7f85431f4 --- /dev/null +++ b/third_party/tizen/tizen_qemu.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import os +import re +import subprocess +import sys + +# Absolute path to Tizen Studio CLI tool. +tizen_sdk_root = os.environ["TIZEN_SDK_ROOT"] + +parser = argparse.ArgumentParser( + description="Run Tizen on QEMU.") +parser.add_argument( + '--smp', metavar='NUM', type=int, default=2, + help=("the number of CPUs available in QEMU; default: %(default)s")) +parser.add_argument( + '--memory', metavar='SIZE', type=int, default=512, + help=("the size of RAM assigned to QEMU; default: %(default)s")) +parser.add_argument( + '--virtio-net', action='store_true', + help="enable external network access via virtio-net") +parser.add_argument( + '--kernel', metavar='PATH', + default=os.path.join(tizen_sdk_root, "iot-qemu-virt-zImage"), + help=("path to the kernel image; " + "default: $TIZEN_SDK_ROOT/iot-qemu-virt-zImage")) +parser.add_argument( + '--image-root', metavar='IMAGE', + default=os.path.join(tizen_sdk_root, "iot-rootfs.img"), + help=("path to the root image; " + "default: $TIZEN_SDK_ROOT/iot-rootfs.img")) +parser.add_argument( + '--image-data', metavar='IMAGE', + default=os.path.join(tizen_sdk_root, "iot-sysdata.img"), + help=("path to the system data image; " + "default: $TIZEN_SDK_ROOT/iot-sysdata.img")) +parser.add_argument( + '--image-iso', metavar='IMAGE', + help=("path to the ISO image with the runner script; the ISO image " + "should have 'CHIP' label and a file named 'runner.sh' at the " + "root directory")) +parser.add_argument( + '--output', metavar='FILE', default="/dev/null", + help="store the QEMU output in a FILE") + +args = parser.parse_args() + +qemu_args = [ + 'qemu-system-arm', + '-monitor', 'null', + '-serial', 'stdio', + '-display', 'none', + '-M', 'virt', + '-smp', str(args.smp), + '-m', str(args.memory), +] + +if args.virtio_net: + # Add network support. + qemu_args += [ + '-device', 'virtio-net-device,netdev=virtio-net', + '-netdev', 'user,id=virtio-net', + ] + +if args.image_iso: + # Add a block device for the runner ISO image. + qemu_args += [ + '-device', 'virtio-blk-device,drive=virtio-blk3', + '-drive', 'file=%s,id=virtio-blk3,if=none,format=raw' % args.image_iso, + ] + +# Add Tizen image block devices. +qemu_args += [ + '-device', 'virtio-blk-device,drive=virtio-blk2', + '-drive', 'file=%s,id=virtio-blk2,if=none,format=raw,readonly=on' % args.image_data, + # XXX: Device for the root image has to be added as the last one so we can + # use /dev/vda as the root device in the kernel command line arguments. + '-device', 'virtio-blk-device,drive=virtio-blk1', + '-drive', 'file=%s,id=virtio-blk1,if=none,format=raw,readonly=on' % args.image_root, +] + +qemu_args += [ + '-kernel', args.kernel, + '-append', "console=ttyAMA0 earlyprintk earlycon root=/dev/vda", +] + +status = 0 +# Run QEMU. +with open(args.output, "wb") as output: + with subprocess.Popen(qemu_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as proc: + for line in iter(proc.stdout.readline, b''): + + # Forward the output to the stdout and the log file. + sys.stdout.write(line.decode(sys.stdout.encoding)) + sys.stdout.flush() + output.write(line) + + # Check if the runner script has finished and save the status. + stop = re.match(rb'^### RUNNER STOP: (?P\d+)', line) + if stop: + status = int(stop.group('status')) + +# Return with the status of the runner script. +sys.exit(status) diff --git a/third_party/tizen/tizen_sdk.gni b/third_party/tizen/tizen_sdk.gni index b3d3d8bc40ecda..0ac79b3fb5ba3a 100644 --- a/third_party/tizen/tizen_sdk.gni +++ b/third_party/tizen/tizen_sdk.gni @@ -20,6 +20,7 @@ import("${build_root}/config/tizen/config.gni") tizen_dev_certificate = get_path_info("tizen_dev_certificate.py", "abspath") tizen_manifest_parser = get_path_info("tizen_manifest_parser.py", "abspath") +tizen_qemu = get_path_info("tizen_qemu.py", "abspath") # Run Tizen Studio CLI as a project builder. # @@ -161,3 +162,73 @@ template("tizen_sdk_package") { ] } } + +# Create ISO image for Tizen QEMU. +# +# Parameters: +# runner: Path to the Tizen QEMU runner script. +# assets: List of assets to copy to the ISO image. +template("tizen_qemu_mkisofs") { + # This target shall only be used for testing purposes. + testonly = true + + assert(defined(invoker.runner), "It is required to specify runner script.") + assert(get_path_info(invoker.runner, "file") == "runner.sh", + "Runner script must be named 'runner.sh'") + + image_file = "${target_gen_dir}/${target_name}.iso" + + action(target_name) { + forward_variables_from(invoker, [ "deps" ]) + inputs = [ invoker.runner ] + outputs = [ image_file ] + + args = [ + "mkisofs", + "-input-charset=default", + "-VCHIP", # Volume ID = CHIP + "-JRU", # Joliet + Rock Ridge with untranslated filenames + "-o", + rebase_path(image_file), + rebase_path(invoker.runner, root_build_dir), + ] + if (defined(invoker.assets)) { + args += invoker.assets + inputs += invoker.assets + } + + script = "${build_root}/gn_run_binary.py" + } +} + +# Run Tizen in QEMU. +# +# Parameters: +# iso_image: The path to ISO image with the runner script. +# virtio_net: Enable external network access. +template("tizen_qemu_run") { + # This target shall only be used for testing purposes. + testonly = true + + assert(defined(invoker.iso_image), + "It is required to specify ISO runner image.") + + # Store QEMU output in a dedicated log file. + output_log_file = "${root_build_dir}/tizen-qemu-" + target_name + ".log" + + action(target_name) { + forward_variables_from(invoker, [ "deps" ]) + inputs = [ invoker.iso_image ] + outputs = [ output_log_file ] + + args = [ + "--image-iso=" + invoker.iso_image, + "--output=" + rebase_path(output_log_file), + ] + if (defined(invoker.virtio_net)) { + args += [ "--virtio-net" ] + } + + script = tizen_qemu + } +}