Skip to content

Commit 8795b3f

Browse files
authored
Adopt swiftlang soundness workflow (#80)
Replaces our lint workflow with a more general solution from the swiftlang/github-workflow repo.
1 parent 34d0bb5 commit 8795b3f

File tree

12 files changed

+155
-100
lines changed

12 files changed

+155
-100
lines changed

.flake8

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[flake8]
2+
3+
ignore =
4+
# These are needed to make our license headers pass the linting
5+
E265,
6+
E266,
7+
8+
# 10% larger than the standard 80 character limit. Conforms to the black
9+
# standard and Bugbear's B950.
10+
max-line-length = 88

.github/workflows/build-esp.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
branches: ["main"]
88
schedule:
99
# Build on Mondays at 9am PST every week
10-
- cron: '0 17 * * 1'
10+
- cron: '0 17 * * 1'
1111

1212
jobs:
1313
build-esp:

.github/workflows/build-nuttx.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
branches: ["main"]
88
schedule:
99
# Build on Mondays at 9am PST every week
10-
- cron: '0 17 * * 1'
10+
- cron: '0 17 * * 1'
1111

1212
jobs:
1313
build-nuttx:

.github/workflows/build-pico-sdk.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
branches: ["main"]
88
schedule:
99
# Build on Mondays at 9am PST every week
10-
- cron: '0 17 * * 1'
10+
- cron: '0 17 * * 1'
1111

1212
jobs:
1313
build-pico-sdk:

.github/workflows/build-zephyr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
branches: ["main"]
88
schedule:
99
# Build on Mondays at 9am PST every week
10-
- cron: '0 17 * * 1'
10+
- cron: '0 17 * * 1'
1111

1212
jobs:
1313
build-zephyr:

.github/workflows/lint.yml

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,26 @@ on:
77
branches: ["main"]
88

99
jobs:
10-
lint:
11-
name: Lint
10+
validate_format_config:
11+
name: Validate Format Config
1212
runs-on: ubuntu-latest
13-
container: swift:6.0-jammy
14-
1513
steps:
1614
- name: Checkout repo
1715
uses: actions/checkout@v4
1816

1917
- name: Install apt dependencies
20-
run: apt-get -qq update && apt-get -qq -y install curl
18+
run: sudo apt-get -qq update && sudo apt-get -qq -y install curl
2119

2220
- name: Compare against swift-mmio swift-format config
2321
run: |
2422
curl -sL https://raw.githubusercontent.com/apple/swift-mmio/refs/heads/main/.swift-format -o .swift-format-mmio
2523
diff .swift-format .swift-format-mmio
2624
27-
- name: Lint
28-
run: swift-format lint --recursive --strict .
25+
soundness:
26+
name: Soundness
27+
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
28+
with:
29+
api_breakage_check_enabled: false # this repo doesn't vend any API
30+
license_header_check_enabled: false # feature: https://github.com/swiftlang/github-workflows/issues/78
31+
license_header_check_project_name: "Swift.org" # bug: https://github.com/swiftlang/github-workflows/issues/76
32+
unacceptable_language_check_enabled: false # unfortunately many hardware specs use terms like master/slave in their documentation

Tools/macho2bin.py

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,45 @@
88
# See https://swift.org/LICENSE.txt for license information
99

1010
#
11-
# macho2bin -- Converts a statically-linked executable Mach-O into a flat "BIN" file suitable for flashing as a single
12-
# contiguous blob onto some embedded devices. Note that this format assumes the embedded device can boot from a state
13-
# where the entire firmware (all segments) are flashed contigously into one smalle address range. This is true for e.g.
14-
# the STM32F746 devices if we place the vector table at 0x00200000, and code and data right after it, as the vector
15-
# table also contains a pointer to the initial PC. This setup might not work for other devices.
11+
# macho2bin -- Converts a statically-linked executable Mach-O into a flat "BIN" file
12+
# suitable for flashing as a single contiguous blob onto some embedded devices. Note
13+
# that this format assumes the embedded device can boot from a state where the entire
14+
# firmware (all segments) are flashed contigously into one smalle address range. This
15+
# is true for e.g. the STM32F746 devices if we place the vector table at 0x00200000,
16+
# and code and data right after it, as the vector table also contains a pointer to the
17+
# initial PC. This setup might not work for other devices.
1618
#
1719
# Usage:
18-
# $ macho2bin.py <input> <output> --base-address <base-address> --segments <segment-list>
20+
# $ macho2bin.py <input> <output> --base-address <base-address> --segments
21+
# <segment-list>
1922
#
2023
# Example:
21-
# $ macho2bin.py ./blink ./blink.bin --base-address 0x00200000 --segments '__TEXT,__DATA,__VECTORS'
24+
# $ macho2bin.py ./blink ./blink.bin --base-address 0x00200000 --segments
25+
# '__TEXT,__DATA,__VECTORS'
2226
#
2327
# Requirements and notes:
24-
# * The output BIN file is a flat contiguous representation of the segments (--segments) based on their VM addresses.
25-
# * The BIN file's first byte corresponds to the specified base address (--base-address).
28+
# * The output BIN file is a flat contiguous representation of the segments
29+
# (--segments) based on their VM addresses.
30+
# * The BIN file's first byte corresponds to the specified base address
31+
# (--base-address).
2632
# * Any gaps between segments are filled with zero bytes.
27-
# * Because of that, you want the input Mach-O to have all segments "close", and not have gaps.
33+
# * Because of that, you want the input Mach-O to have all segments "close", and not
34+
# have gaps.
2835
#
2936

3037
import argparse
3138
import os
39+
3240
from macholib import MachO
3341
from macholib import mach_o
3442

43+
3544
def main():
3645
parser = argparse.ArgumentParser()
37-
parser.add_argument('input')
38-
parser.add_argument('output')
39-
parser.add_argument('--base-address', required=True)
40-
parser.add_argument('--segments', required=True)
46+
parser.add_argument("input")
47+
parser.add_argument("output")
48+
parser.add_argument("--base-address", required=True)
49+
parser.add_argument("--segments", required=True)
4150
args = parser.parse_args()
4251
args.base_address = int(args.base_address, 16)
4352
args.segments = args.segments.split(",")
@@ -49,17 +58,23 @@ def main():
4958
for command in mh.commands:
5059
if isinstance(command[1], mach_o.segment_command):
5160
(_, segment, sections) = command
52-
segname = segment.segname.decode().strip('\0')
53-
if segname not in args.segments: continue
61+
segname = segment.segname.decode().strip("\0")
62+
if segname not in args.segments:
63+
continue
5464

5565
with open(args.input, "rb") as f:
5666
f.seek(mh.offset + segment.fileoff)
5767
data = f.read(segment.filesize)
58-
segments.append({"vmaddr": segment.vmaddr, "data": data, "name": segname})
59-
68+
segments.append(
69+
{"vmaddr": segment.vmaddr, "data": data, "name": segname}
70+
)
71+
6072
segments = sorted(segments, key=lambda x: x["vmaddr"])
6173

62-
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}"
74+
assert segments[0]["vmaddr"] == args.base_address, (
75+
f"first segment's vmaddr 0x{segments[0]['vmaddr']:08x} does not match the"
76+
f" passed --base-address 0x{args.base_address:08x}"
77+
)
6378

6479
if os.path.exists(args.output):
6580
os.unlink(args.output)
@@ -69,15 +84,22 @@ def main():
6984
for segment in segments:
7085
gap = segment["vmaddr"] - vmaddr
7186
if gap != 0:
72-
print(f"Writing gap of size {gap} (0x{gap:0x}) at vmaddr 0x{vmaddr:08x}")
73-
f.write(b'\0' * gap)
87+
print(
88+
f"Writing gap of size {gap} (0x{gap:0x}) at vmaddr 0x{vmaddr:08x}"
89+
)
90+
f.write(b"\0" * gap)
7491
assert gap >= 0
7592
vmaddr = segment["vmaddr"]
76-
print(f"Writing segment {segment['name']} size {len(segment['data'])} (0x{len(segment['data']):x}) at vmaddr 0x{vmaddr:08x}")
93+
print(
94+
f"Writing segment {segment['name']} size"
95+
f" {len(segment['data'])} (0x{len(segment['data']):x}) at vmaddr"
96+
f" 0x{vmaddr:08x}"
97+
)
7798
f.write(segment["data"])
7899
vmaddr = segment["vmaddr"] + len(segment["data"])
79100

80101
print(f"Produced {args.output} with {vmaddr - args.base_address} bytes")
81102

82-
if __name__ == '__main__':
103+
104+
if __name__ == "__main__":
83105
main()

Tools/macho2uf2.py

Lines changed: 60 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,80 +8,97 @@
88
# See https://swift.org/LICENSE.txt for license information
99

1010
#
11-
# macho2uf2 -- Converts a statically-linked executable Mach-O into a flat "UF2" file suitable for flashing as a single
12-
# contiguous blob onto some embedded devices, in particular Raspberry Pi Pico (W). Note that the UF2 format allows for
13-
# discontiguous memory regions, but this utility does not support that.
11+
# macho2uf2 -- Converts a statically-linked executable Mach-O into a flat "UF2" file
12+
# suitable for flashing as a single contiguous blob onto some embedded devices, in
13+
# particular Raspberry Pi Pico (W). Note that the UF2 format allows for discontiguous
14+
# memory regions, but this utility does not support that.
1415
#
1516
# Usage:
16-
# $ macho2uf2.py <input> <output> --base-address <base-address> --segments <segment-list>
17+
# $ macho2uf2.py <input> <output> --base-address <base-address> --segments
18+
# <segment-list>
1719
#
1820
# Example:
19-
# $ macho2uf2.py ./blink ./blink.uf2 --base-address 0x00200000 --segments '__TEXT,__DATA,__VECTORS'
21+
# $ macho2uf2.py ./blink ./blink.uf2 --base-address 0x00200000 --segments
22+
# '__TEXT,__DATA,__VECTORS'
2023
#
2124
# Requirements and notes:
22-
# * The output UF2 file is a flat contiguous representation of the segments (--segments) based on their VM addresses.
23-
# * The UF2 file's first byte corresponds to the specified base address (--base-address).
25+
# * The output UF2 file is a flat contiguous representation of the segments
26+
# (--segments) based on their VM addresses.
27+
# * The UF2 file's first byte corresponds to the specified base address
28+
# (--base-address).
2429
# * Any gaps between segments are filled with zero bytes.
25-
# * Because of that, you want the input Mach-O to have all segments "close", and not have gaps.
30+
# * Because of that, you want the input Mach-O to have all segments "close", and not
31+
# have gaps.
2632
#
2733

2834
import argparse
2935
import os
30-
import subprocess
3136
import struct
32-
from macholib import MachO
33-
from macholib import mach_o
37+
import subprocess
3438

3539
MY_DIR = os.path.dirname(os.path.abspath(__file__))
3640

41+
3742
def main():
3843
parser = argparse.ArgumentParser()
39-
parser.add_argument('input')
40-
parser.add_argument('output')
41-
parser.add_argument('--base-address', required=True)
42-
parser.add_argument('--segments', required=True)
43-
parser.add_argument('--pico-family', required=True)
44+
parser.add_argument("input")
45+
parser.add_argument("output")
46+
parser.add_argument("--base-address", required=True)
47+
parser.add_argument("--segments", required=True)
48+
parser.add_argument("--pico-family", required=True)
4449
args = parser.parse_args()
4550
args.base_address = int(args.base_address, 16)
4651
args.segments = args.segments.split(",")
4752
if args.pico_family == "rp2040":
4853
family_id = 0xE48BFF56
4954
add_errata_block = False
5055
elif args.pico_family == "rp2350":
51-
family_id = 0XE48BFF59
56+
family_id = 0xE48BFF59
5257
add_errata_block = True
5358
else:
5459
assert False
5560

56-
subprocess.check_call([MY_DIR + "/macho2bin.py", args.input, args.input + ".bin", "--base-address", "0x%08x" % args.base_address, "--segments", ",".join(args.segments)])
61+
subprocess.check_call(
62+
[
63+
MY_DIR + "/macho2bin.py",
64+
args.input,
65+
args.input + ".bin",
66+
"--base-address",
67+
"0x%08x" % args.base_address,
68+
"--segments",
69+
",".join(args.segments),
70+
]
71+
)
5772

5873
def emit_block(output, block, vmaddr, block_number, num_blocks, family_id):
5974
assert len(block) <= 256
60-
75+
6176
if len(block) < 256:
62-
block += b'\0' * (256 - len(block))
63-
77+
block += b"\0" * (256 - len(block))
78+
6479
# UF2_Block header
65-
output += struct.pack("<I", 0x0A324655) # magicStart0
66-
output += struct.pack("<I", 0x9E5D5157) # magicStart1
67-
output += struct.pack("<I", 0x2000) # flags: familyID present
68-
output += struct.pack("<I", vmaddr) # targetAddr
69-
output += struct.pack("<I", 256) # payloadSize
70-
output += struct.pack("<I", block_number) # blockNo
71-
output += struct.pack("<I", num_blocks) # numBlocks
72-
output += struct.pack("<I", family_id) # fileSize / familyID: rp2040/rp2350 family ID
80+
output += struct.pack("<I", 0x0A324655) # magicStart0
81+
output += struct.pack("<I", 0x9E5D5157) # magicStart1
82+
output += struct.pack("<I", 0x2000) # flags: familyID present
83+
output += struct.pack("<I", vmaddr) # targetAddr
84+
output += struct.pack("<I", 256) # payloadSize
85+
output += struct.pack("<I", block_number) # blockNo
86+
output += struct.pack("<I", num_blocks) # numBlocks
87+
output += struct.pack(
88+
"<I", family_id
89+
) # fileSize / familyID: rp2040/rp2350 family ID
7390

7491
# Data
7592
if len(block) < 476:
76-
block += b'\0' * (476 - len(block))
93+
block += b"\0" * (476 - len(block))
7794
output += block
7895

7996
# UF2_Block footer
80-
output += struct.pack("<I", 0x0AB16F30) # magicEnd
81-
97+
output += struct.pack("<I", 0x0AB16F30) # magicEnd
98+
8299
return output
83100

84-
output = b''
101+
output = b""
85102
with open(args.input + ".bin", "rb") as f:
86103
if add_errata_block:
87104
# RP2350-E10 errata
@@ -97,14 +114,20 @@ def emit_block(output, block, vmaddr, block_number, num_blocks, family_id):
97114
block = f.read(256)
98115
if len(block) == 0:
99116
break
100-
output = emit_block(output, block, vmaddr, block_number, num_blocks, family_id)
117+
output = emit_block(
118+
output, block, vmaddr, block_number, num_blocks, family_id
119+
)
101120
block_number += 1
102121
vmaddr += 256
103122

104123
with open(args.output, "wb") as f:
105124
f.write(output)
106-
107-
print(f"Produced {args.output} with total size {len(output)} (0x{len(output):0x}) bytes, payload size {total_size} (0x{total_size:0x}) bytes")
108125

109-
if __name__ == '__main__':
126+
print(
127+
f"Produced {args.output} with total size {len(output)} (0x{len(output):0x})"
128+
f" bytes, payload size {total_size} (0x{total_size:0x}) bytes"
129+
)
130+
131+
132+
if __name__ == "__main__":
110133
main()

nrfx-blink-sdk/west.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ manifest:
99
revision: main
1010
import:
1111
name-allowlist:
12-
- cmsis # required by the ARM port
13-
- hal_nordic # required by the custom_plank board (Nordic based)
12+
- cmsis # required by the ARM port
13+
- hal_nordic # required by the custom_plank board (Nordic based)

0 commit comments

Comments
 (0)