From 914a3798290e3b41d75aa07c950a90ef87bbad56 Mon Sep 17 00:00:00 2001 From: Rauhul Varma Date: Sun, 15 Dec 2024 15:20:43 -0800 Subject: [PATCH 1/7] Adopt swiftlang soundness workflow Replaces our lint workflow with a more general solution from the swiftlang/github-workflow repo. --- .github/workflows/lint.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 52009c0a..3d7eac4a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -7,22 +7,25 @@ on: branches: ["main"] jobs: - lint: - name: Lint + validate_format_config: + name: Validate Format Config runs-on: ubuntu-latest - container: swift:6.0-jammy - steps: - name: Checkout repo uses: actions/checkout@v4 - name: Install apt dependencies - run: apt-get -qq update && apt-get -qq -y install curl + run: sudo apt-get -qq update && sudo apt-get -qq -y install curl - name: Compare against swift-mmio swift-format config run: | curl -sL https://raw.githubusercontent.com/apple/swift-mmio/refs/heads/main/.swift-format -o .swift-format-mmio diff .swift-format .swift-format-mmio - - name: Lint - run: swift-format lint --recursive --strict . + soundness: + name: Soundness + uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main + with: + api_breakage_check_enabled: false # this repo doesn't vend any API + license_header_check_enabled: false # feature: https://github.com/swiftlang/github-workflows/issues/78 + license_header_check_project_name: "Swift.org" # bug: https://github.com/swiftlang/github-workflows/issues/76 From ff3fe8137ec272352098b03c86f947dbdbabd299 Mon Sep 17 00:00:00 2001 From: Rauhul Varma Date: Sun, 15 Dec 2024 15:46:14 -0800 Subject: [PATCH 2/7] wip --- .github/workflows/build-esp.yml | 2 +- .github/workflows/build-pico-sdk.yml | 2 +- .github/workflows/build-zephyr.yml | 2 +- Tools/macho2bin.py | 68 ++++++++++++------- Tools/macho2uf2.py | 97 +++++++++++++++++----------- nrfx-blink-sdk/west.yml | 5 +- 6 files changed, 111 insertions(+), 65 deletions(-) diff --git a/.github/workflows/build-esp.yml b/.github/workflows/build-esp.yml index 0def652e..b6efe03f 100644 --- a/.github/workflows/build-esp.yml +++ b/.github/workflows/build-esp.yml @@ -7,7 +7,7 @@ on: branches: ["main"] schedule: # Build on Mondays at 9am PST every week - - cron: '0 17 * * 1' + - cron: '0 17 * * 1' jobs: build-esp: diff --git a/.github/workflows/build-pico-sdk.yml b/.github/workflows/build-pico-sdk.yml index 06283bd6..67b76008 100644 --- a/.github/workflows/build-pico-sdk.yml +++ b/.github/workflows/build-pico-sdk.yml @@ -7,7 +7,7 @@ on: branches: ["main"] schedule: # Build on Mondays at 9am PST every week - - cron: '0 17 * * 1' + - cron: '0 17 * * 1' jobs: build-pico-sdk: diff --git a/.github/workflows/build-zephyr.yml b/.github/workflows/build-zephyr.yml index 0233f150..51b507ed 100644 --- a/.github/workflows/build-zephyr.yml +++ b/.github/workflows/build-zephyr.yml @@ -7,7 +7,7 @@ on: branches: ["main"] schedule: # Build on Mondays at 9am PST every week - - cron: '0 17 * * 1' + - cron: '0 17 * * 1' jobs: build-zephyr: diff --git a/Tools/macho2bin.py b/Tools/macho2bin.py index 9b348f38..6ba74b3c 100755 --- a/Tools/macho2bin.py +++ b/Tools/macho2bin.py @@ -8,36 +8,45 @@ # See https://swift.org/LICENSE.txt for license information # -# macho2bin -- Converts a statically-linked executable Mach-O into a flat "BIN" file suitable for flashing as a single -# contiguous blob onto some embedded devices. Note that this format assumes the embedded device can boot from a state -# where the entire firmware (all segments) are flashed contigously into one smalle address range. This is true for e.g. -# the STM32F746 devices if we place the vector table at 0x00200000, and code and data right after it, as the vector -# table also contains a pointer to the initial PC. This setup might not work for other devices. +# macho2bin -- Converts a statically-linked executable Mach-O into a flat "BIN" file +# suitable for flashing as a single contiguous blob onto some embedded devices. Note +# that this format assumes the embedded device can boot from a state where the entire +# firmware (all segments) are flashed contigously into one smalle address range. This +# is true for e.g. the STM32F746 devices if we place the vector table at 0x00200000, +# and code and data right after it, as the vector table also contains a pointer to the +# initial PC. This setup might not work for other devices. # # Usage: -# $ macho2bin.py --base-address --segments +# $ macho2bin.py --base-address --segments +# # # Example: -# $ macho2bin.py ./blink ./blink.bin --base-address 0x00200000 --segments '__TEXT,__DATA,__VECTORS' +# $ macho2bin.py ./blink ./blink.bin --base-address 0x00200000 --segments +# '__TEXT,__DATA,__VECTORS' # # Requirements and notes: -# * The output BIN file is a flat contiguous representation of the segments (--segments) based on their VM addresses. -# * The BIN file's first byte corresponds to the specified base address (--base-address). +# * The output BIN file is a flat contiguous representation of the segments +# (--segments) based on their VM addresses. +# * The BIN file's first byte corresponds to the specified base address +# (--base-address). # * Any gaps between segments are filled with zero bytes. -# * Because of that, you want the input Mach-O to have all segments "close", and not have gaps. +# * Because of that, you want the input Mach-O to have all segments "close", and not +# have gaps. # import argparse import os + from macholib import MachO from macholib import mach_o + def main(): parser = argparse.ArgumentParser() - parser.add_argument('input') - parser.add_argument('output') - parser.add_argument('--base-address', required=True) - parser.add_argument('--segments', required=True) + parser.add_argument("input") + parser.add_argument("output") + parser.add_argument("--base-address", required=True) + parser.add_argument("--segments", required=True) args = parser.parse_args() args.base_address = int(args.base_address, 16) args.segments = args.segments.split(",") @@ -49,17 +58,23 @@ def main(): for command in mh.commands: if isinstance(command[1], mach_o.segment_command): (_, segment, sections) = command - segname = segment.segname.decode().strip('\0') - if segname not in args.segments: continue + segname = segment.segname.decode().strip("\0") + if segname not in args.segments: + continue with open(args.input, "rb") as f: f.seek(mh.offset + segment.fileoff) data = f.read(segment.filesize) - segments.append({"vmaddr": segment.vmaddr, "data": data, "name": segname}) - + segments.append( + {"vmaddr": segment.vmaddr, "data": data, "name": segname} + ) + segments = sorted(segments, key=lambda x: x["vmaddr"]) - assert segments[0]["vmaddr"] == args.base_address, f"first segment's vmaddr 0x{segments[0]['vmaddr']:08x} does not match the passed --base-address 0x{args.base_address:08x}" + assert segments[0]["vmaddr"] == args.base_address, ( + f"first segment's vmaddr 0x{segments[0]['vmaddr']:08x} does not match the" + f" passed --base-address 0x{args.base_address:08x}" + ) if os.path.exists(args.output): os.unlink(args.output) @@ -69,15 +84,22 @@ def main(): for segment in segments: gap = segment["vmaddr"] - vmaddr if gap != 0: - print(f"Writing gap of size {gap} (0x{gap:0x}) at vmaddr 0x{vmaddr:08x}") - f.write(b'\0' * gap) + print( + f"Writing gap of size {gap} (0x{gap:0x}) at vmaddr 0x{vmaddr:08x}" + ) + f.write(b"\0" * gap) assert gap >= 0 vmaddr = segment["vmaddr"] - print(f"Writing segment {segment['name']} size {len(segment['data'])} (0x{len(segment['data']):x}) at vmaddr 0x{vmaddr:08x}") + print( + f"Writing segment {segment['name']} size" + f" {len(segment['data'])} (0x{len(segment['data']):x}) at vmaddr" + f" 0x{vmaddr:08x}" + ) f.write(segment["data"]) vmaddr = segment["vmaddr"] + len(segment["data"]) print(f"Produced {args.output} with {vmaddr - args.base_address} bytes") -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/Tools/macho2uf2.py b/Tools/macho2uf2.py index f0812e0b..5043b4a8 100755 --- a/Tools/macho2uf2.py +++ b/Tools/macho2uf2.py @@ -8,39 +8,44 @@ # See https://swift.org/LICENSE.txt for license information # -# macho2uf2 -- Converts a statically-linked executable Mach-O into a flat "UF2" file suitable for flashing as a single -# contiguous blob onto some embedded devices, in particular Raspberry Pi Pico (W). Note that the UF2 format allows for -# discontiguous memory regions, but this utility does not support that. +# macho2uf2 -- Converts a statically-linked executable Mach-O into a flat "UF2" file +# suitable for flashing as a single contiguous blob onto some embedded devices, in +# particular Raspberry Pi Pico (W). Note that the UF2 format allows for discontiguous +# memory regions, but this utility does not support that. # # Usage: -# $ macho2uf2.py --base-address --segments +# $ macho2uf2.py --base-address --segments +# # # Example: -# $ macho2uf2.py ./blink ./blink.uf2 --base-address 0x00200000 --segments '__TEXT,__DATA,__VECTORS' +# $ macho2uf2.py ./blink ./blink.uf2 --base-address 0x00200000 --segments +# '__TEXT,__DATA,__VECTORS' # # Requirements and notes: -# * The output UF2 file is a flat contiguous representation of the segments (--segments) based on their VM addresses. -# * The UF2 file's first byte corresponds to the specified base address (--base-address). +# * The output UF2 file is a flat contiguous representation of the segments +# (--segments) based on their VM addresses. +# * The UF2 file's first byte corresponds to the specified base address +# (--base-address). # * Any gaps between segments are filled with zero bytes. -# * Because of that, you want the input Mach-O to have all segments "close", and not have gaps. +# * Because of that, you want the input Mach-O to have all segments "close", and not +# have gaps. # import argparse import os -import subprocess import struct -from macholib import MachO -from macholib import mach_o +import subprocess MY_DIR = os.path.dirname(os.path.abspath(__file__)) + def main(): parser = argparse.ArgumentParser() - parser.add_argument('input') - parser.add_argument('output') - parser.add_argument('--base-address', required=True) - parser.add_argument('--segments', required=True) - parser.add_argument('--pico-family', required=True) + parser.add_argument("input") + parser.add_argument("output") + parser.add_argument("--base-address", required=True) + parser.add_argument("--segments", required=True) + parser.add_argument("--pico-family", required=True) args = parser.parse_args() args.base_address = int(args.base_address, 16) args.segments = args.segments.split(",") @@ -48,40 +53,52 @@ def main(): family_id = 0xE48BFF56 add_errata_block = False elif args.pico_family == "rp2350": - family_id = 0XE48BFF59 + family_id = 0xE48BFF59 add_errata_block = True else: assert False - subprocess.check_call([MY_DIR + "/macho2bin.py", args.input, args.input + ".bin", "--base-address", "0x%08x" % args.base_address, "--segments", ",".join(args.segments)]) + subprocess.check_call( + [ + MY_DIR + "/macho2bin.py", + args.input, + args.input + ".bin", + "--base-address", + "0x%08x" % args.base_address, + "--segments", + ",".join(args.segments), + ] + ) def emit_block(output, block, vmaddr, block_number, num_blocks, family_id): assert len(block) <= 256 - + if len(block) < 256: - block += b'\0' * (256 - len(block)) - + block += b"\0" * (256 - len(block)) + # UF2_Block header - output += struct.pack(" Date: Sun, 15 Dec 2024 17:01:13 -0800 Subject: [PATCH 3/7] wip --- .flake8 | 10 ++++++++++ nrfx-blink-sdk/west.yml | 1 - 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..c7b743c5 --- /dev/null +++ b/.flake8 @@ -0,0 +1,10 @@ +[flake8] + +ignore = + # These are needed to make our license headers pass the linting + E265, + E266, + +# 10% larger than the standard 80 character limit. Conforms to the black +# standard and Bugbear's B950. +max-line-length = 88 diff --git a/nrfx-blink-sdk/west.yml b/nrfx-blink-sdk/west.yml index 5ed86312..e02dd56d 100644 --- a/nrfx-blink-sdk/west.yml +++ b/nrfx-blink-sdk/west.yml @@ -11,4 +11,3 @@ manifest: name-allowlist: - cmsis # required by the ARM port - hal_nordic # required by the custom_plank board (Nordic based) - From cec021c595c22e581fd5aefc770b45ee0f126048 Mon Sep 17 00:00:00 2001 From: Rauhul Varma Date: Thu, 2 Jan 2025 23:38:17 -0800 Subject: [PATCH 4/7] update --- .github/workflows/lint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 3d7eac4a..da68cece 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -29,3 +29,4 @@ jobs: api_breakage_check_enabled: false # this repo doesn't vend any API license_header_check_enabled: false # feature: https://github.com/swiftlang/github-workflows/issues/78 license_header_check_project_name: "Swift.org" # bug: https://github.com/swiftlang/github-workflows/issues/76 + unacceptable_language_check_enabled: false # unfortunately many hardware specs use terms like master/slave in their documentation From 2efbf9db04fc7e079dfe3ba02417282a2a46b0fd Mon Sep 17 00:00:00 2001 From: Rauhul Varma Date: Thu, 2 Jan 2025 23:41:32 -0800 Subject: [PATCH 5/7] update --- .github/workflows/build-nuttx.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-nuttx.yml b/.github/workflows/build-nuttx.yml index 952fc7ec..f9104e52 100644 --- a/.github/workflows/build-nuttx.yml +++ b/.github/workflows/build-nuttx.yml @@ -7,7 +7,7 @@ on: branches: ["main"] schedule: # Build on Mondays at 9am PST every week - - cron: '0 17 * * 1' + - cron: '0 17 * * 1' jobs: build-nuttx: From 1020c2a15ff399742e7c1c7eece97aff7b5878d1 Mon Sep 17 00:00:00 2001 From: Rauhul Varma Date: Thu, 2 Jan 2025 23:49:11 -0800 Subject: [PATCH 6/7] fix shellcheck --- pico-blink/build.sh | 20 ++++++++++---------- stm32-blink/build.sh | 26 +++++++++++++------------- stm32-lcd-logo/build.sh | 4 ---- 3 files changed, 23 insertions(+), 27 deletions(-) delete mode 100755 stm32-lcd-logo/build.sh diff --git a/pico-blink/build.sh b/pico-blink/build.sh index 6240eae4..8fbf37c7 100755 --- a/pico-blink/build.sh +++ b/pico-blink/build.sh @@ -10,35 +10,35 @@ REPOROOT=$(git rev-parse --show-toplevel) TOOLSROOT=$REPOROOT/Tools # Setup tools and build flags -SWIFT_EXEC=${SWIFT_EXEC:-`xcrun -f swift`} -CLANG=${CLANG:-`xcrun -f clang`} +SWIFT_EXEC=${SWIFT_EXEC:-$(xcrun -f swift)} +CLANG=${CLANG:-$(xcrun -f clang)} SWIFT_FLAGS="-enable-experimental-feature Embedded -disable-stack-protector" CLANG_FLAGS="-D__MACH__ -ffreestanding -mcpu=cortex-m0plus -mthumb" LD_FLAGS="-static -Wl,-e,_reset -dead_strip -Wl,-no_zero_fill_sections -Wl,-segalign,4 -Wl,-segaddr,__RESET,0x20000000 -Wl,-segaddr,__VECTORS,0x20000100 -Wl,-seg1addr,0x20000200 -Wl,-pagezero_size,0" SWIFT_BUILD_FLAGS="--triple armv6m-apple-none-macho --configuration release --verbose" for SWIFT_FLAG in $SWIFT_FLAGS; do - SWIFT_BUILD_FLAGS+=" -Xswiftc $SWIFT_FLAG" + SWIFT_BUILD_FLAGS="$SWIFT_BUILD_FLAGS -Xswiftc $SWIFT_FLAG" done for CLANG_FLAG in $CLANG_FLAGS; do - SWIFT_BUILD_FLAGS+=" -Xcc $CLANG_FLAG" + SWIFT_BUILD_FLAGS="$SWIFT_BUILD_FLAGS -Xcc $CLANG_FLAG" done -PYTHON_EXEC=${PYTHON_EXEC:-`xcrun -f python3`} +PYTHON_EXEC=${PYTHON_EXEC:-$(xcrun -f python3)} MACHO2UF2=$TOOLSROOT/macho2uf2.py # Build with Swift package manager -$SWIFT_EXEC build $SWIFT_BUILD_FLAGS +$SWIFT_EXEC build "$SWIFT_BUILD_FLAGS" # Get the output directory -BUILDROOT=$($SWIFT_EXEC build $SWIFT_BUILD_FLAGS --show-bin-path) +BUILDROOT=$($SWIFT_EXEC build "$SWIFT_BUILD_FLAGS" --show-bin-path) # Link -$CLANG .build/release/Support.build/{Support.c,crt0.S}.o .build/release/Blinky.build/*.o -target armv6m-apple-none-macho -o $BUILDROOT/blinky $LD_FLAGS +$CLANG .build/release/Support.build/Support.c.o .build/release/Support.build/crt0.S.o .build/release/Blinky.build/*.o -target armv6m-apple-none-macho -o "$BUILDROOT"/blinky "$LD_FLAGS" # Extract sections from executable into flashable binary -$PYTHON_EXEC $MACHO2UF2 --pico-family $PICO_FAMILY $BUILDROOT/blinky $BUILDROOT/blinky.uf2 --base-address 0x20000000 --segments '__TEXT,__DATA,__VECTORS,__RESET' +$PYTHON_EXEC "$MACHO2UF2" --pico-family $PICO_FAMILY "$BUILDROOT"/blinky "$BUILDROOT"/blinky.uf2 --base-address 0x20000000 --segments '__TEXT,__DATA,__VECTORS,__RESET' # Echo final binary path -ls -al $BUILDROOT/blinky.uf2 +ls -al "$BUILDROOT"/blinky.uf2 diff --git a/stm32-blink/build.sh b/stm32-blink/build.sh index b9e1e270..adc54c8c 100755 --- a/stm32-blink/build.sh +++ b/stm32-blink/build.sh @@ -4,39 +4,39 @@ set -vex # Determine file paths REPOROOT=$(git rev-parse --show-toplevel) -TOOLSROOT=$REPOROOT/Tools -SRCROOT=$REPOROOT/stm32-blink -BUILDROOT=$SRCROOT/.build +TOOLSROOT="$REPOROOT/Tools" +SRCROOT="$REPOROOT/stm32-blink" +BUILDROOT="$SRCROOT/.build" # Setup tools and build flags TARGET=armv7-apple-none-macho -SWIFT_EXEC=${SWIFT_EXEC:-`xcrun -f swiftc`} +SWIFT_EXEC=${SWIFT_EXEC:-$(xcrun -f swiftc)} SWIFT_FLAGS="-target $TARGET -Osize -import-bridging-header $SRCROOT/BridgingHeader.h -wmo -enable-experimental-feature Embedded -Xcc -D__APPLE__ -Xcc -D__MACH__ -Xcc -ffreestanding" -CLANG_EXEC=${CLANG_EXEC:-`xcrun -f clang`} +CLANG_EXEC=${CLANG_EXEC:-$(xcrun -f clang)} CLANG_FLAGS="-target $TARGET -Oz" LD_EXEC=${LD_EXEC:-$CLANG_EXEC} LD_FLAGS="-target $TARGET -nostdlib -static -Wl,-e,_reset -dead_strip -Wl,-no_zero_fill_sections -Wl,-segalign,4 -Wl,-segaddr,__VECTORS,0x00200000 -Wl,-seg1addr,0x00200200 -Wl,-pagezero_size,0" -PYTHON_EXEC=${PYTHON_EXEC:-`xcrun -f python3`} -MACHO2BIN=$TOOLSROOT/macho2bin.py +PYTHON_EXEC=${PYTHON_EXEC:-$(xcrun -f python3)} +MACHO2BIN="$TOOLSROOT/macho2bin.py" # Create build directory -mkdir -p $BUILDROOT +mkdir -p "$BUILDROOT" # Build Swift sources -$SWIFT_EXEC $SWIFT_FLAGS -c $SRCROOT/*.swift -o $BUILDROOT/blink.o +"$SWIFT_EXEC" "$SWIFT_FLAGS" -c "$SRCROOT/*.swift" -o "$BUILDROOT/blink.o" # Build C sources -$CLANG_EXEC $CLANG_FLAGS -c $SRCROOT/Startup.c -o $BUILDROOT/Startup.o +"$CLANG_EXEC" "$CLANG_FLAGS" -c "$SRCROOT/Startup.c" -o "$BUILDROOT/Startup.o" # Link objects into executable -$LD_EXEC $LD_FLAGS $BUILDROOT/blink.o $BUILDROOT/Startup.o -o $BUILDROOT/blink +"$LD_EXEC" "$LD_FLAGS" "$BUILDROOT/blink.o" "$BUILDROOT/Startup.o" -o "$BUILDROOT/blink" # Extract sections from executable into flashable binary -$PYTHON_EXEC $MACHO2BIN $BUILDROOT/blink $BUILDROOT/blink.bin --base-address 0x00200000 --segments '__TEXT,__DATA,__VECTORS' +"$PYTHON_EXEC" "$MACHO2BIN" "$BUILDROOT/blink" "$BUILDROOT/blink.bin" --base-address 0x00200000 --segments '__TEXT,__DATA,__VECTORS' # Echo final binary path -ls -al $BUILDROOT/blink.bin +ls -al "$BUILDROOT/blink.bin" diff --git a/stm32-lcd-logo/build.sh b/stm32-lcd-logo/build.sh deleted file mode 100755 index 465f054b..00000000 --- a/stm32-lcd-logo/build.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -# Build firmware using make -make -j From 034127214224bc8848b0ffb96e26b66f8a58dfce Mon Sep 17 00:00:00 2001 From: Rauhul Varma Date: Thu, 2 Jan 2025 23:52:29 -0800 Subject: [PATCH 7/7] yml --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index da68cece..33b86f83 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -29,4 +29,4 @@ jobs: api_breakage_check_enabled: false # this repo doesn't vend any API license_header_check_enabled: false # feature: https://github.com/swiftlang/github-workflows/issues/78 license_header_check_project_name: "Swift.org" # bug: https://github.com/swiftlang/github-workflows/issues/76 - unacceptable_language_check_enabled: false # unfortunately many hardware specs use terms like master/slave in their documentation + unacceptable_language_check_enabled: false # unfortunately many hardware specs use terms like master/slave in their documentation