Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
32 changes: 32 additions & 0 deletions .github/actions/setup-llgo/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: "Setup LLGO"
description: "Checkout and build LLGO from specific commit hash"
inputs:
commit-hash:
description: "Commit hash to checkout"
required: true
platform:
description: "Platform to download for"
required: false
default: "linux-amd64"
runs:
using: "composite"
steps:
- name: Setup LLGo Dependencies
uses: goplus/llgo/.github/actions/setup-deps@b25ae1b4e7c06a302d1d09eb9e9b0ad1e3a43abd
- name: Checkout LLGo Repository
uses: actions/checkout@v4
with:
repository: goplus/llgo
ref: ${{ inputs.commit-hash }}
path: llgo-source
- name: Setup LLGO
shell: bash
run: |
echo "Setting up LLGO from commit hash ${{ inputs.commit-hash }}..."
cd llgo-source
# Install LLGO from source
bash ./install.sh
# Set LLGO_ROOT to the source directory
echo "LLGO_ROOT=$PWD" >> $GITHUB_ENV
# Verify LLGO is available
llgo version || echo "Failed to get LLGO version"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The llgo version verification step currently echoes a message on failure but allows the action to continue. This could mask installation or setup problems. To ensure the integrity of the setup, this step should fail if llgo is not found or fails to report its version.

        llgo version

335 changes: 335 additions & 0 deletions .github/scripts/device-gen.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,335 @@
#!/bin/bash
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation: Missing Script Header

Add documentation explaining the script's purpose, usage, and modes:

#!/bin/bash
#
# device-gen.sh - Generate device files from upstream hardware description files
#
# Usage: ./device-gen.sh [generate|verify]
#
# Modes:
#   generate - Clean target directories and regenerate all device files
#   verify   - Verify generated files match existing files (for CI)
#   (default) - Generate without cleaning (preserves ignore list files)
#
set -e

set -e

# .ld,.s current not need generate at emb/device/avr,they are in llgo

declare_avr_config() {
name="avr"
repo="https://github.com/avr-rust/avr-mcu"
lib_path="lib/avr"
git_hash="6624554c02b237b23dc17d53e992bf54033fc228"
tasks=(
"lib/avr/packs/atmega"
"lib/avr/packs/tiny"
)
ignore_list="avr.go avr_tiny85.go"
target="device/avr"
generator="gen-device-avr"
}

declare_esp_config() {
name="esp"
repo="https://github.com/cmsis-svd/cmsis-svd-data"
lib_path="lib/cmsis-svd"
git_hash="05a9562ec59b87945a8d7177a4b08b7aa2f2fd58"
tasks=(
"-source=https://github.com/posborne/cmsis-svd/tree/master/data/Espressif-Community -interrupts=software lib/cmsis-svd/data/Espressif-Community/"
"-source=https://github.com/posborne/cmsis-svd/tree/master/data/Espressif -interrupts=software lib/cmsis-svd/data/Espressif/"
)
ignore_list=""
target="device/esp"
generator="gen-device-svd"
}

declare_nrf_config() {
name="nrf"
repo="https://github.com/NordicSemiconductor/nrfx"
lib_path="lib/nrfx"
git_hash="d779b49fc59c7a165e7da1d7cd7d57b28a059f16"
tasks=(
"-source=https://github.com/NordicSemiconductor/nrfx/tree/master/mdk lib/nrfx/mdk/"
)
ignore_list="README.markdown"
target="device/nrf"
generator="gen-device-svd"
}

declare_nxp_config() {
name="nxp"
repo="https://github.com/cmsis-svd/cmsis-svd-data"
lib_path="lib/cmsis-svd"
git_hash="05a9562ec59b87945a8d7177a4b08b7aa2f2fd58"
tasks=(
"-source=https://github.com/posborne/cmsis-svd/tree/master/data/NXP lib/cmsis-svd/data/NXP/"
)
ignore_list="hardfault.go mimxrt1062_clock.go mimxrt1062_hardfault.go mimxrt1062_mpu.go"
target="device/nxp"
generator="gen-device-svd"
}

declare_sam_config() {
name="sam"
repo="https://github.com/cmsis-svd/cmsis-svd-data"
lib_path="lib/cmsis-svd"
git_hash="05a9562ec59b87945a8d7177a4b08b7aa2f2fd58"
tasks=(
"-source=https://github.com/posborne/cmsis-svd/tree/master/data/Atmel lib/cmsis-svd/data/Atmel/"
)
ignore_list="atsamd51x-bitfields.go atsame5x-bitfields.go"
target="device/sam"
generator="gen-device-svd"
}

declare_sifive_config() {
name="sifive"
repo="https://github.com/cmsis-svd/cmsis-svd-data"
lib_path="lib/cmsis-svd"
git_hash="05a9562ec59b87945a8d7177a4b08b7aa2f2fd58"
tasks=(
"-source=https://github.com/posborne/cmsis-svd/tree/master/data/SiFive-Community -interrupts=software lib/cmsis-svd/data/SiFive-Community/"
)
ignore_list=""
target="device/sifive"
generator="gen-device-svd"
}

declare_kendryte_config() {
name="kendryte"
repo="https://github.com/cmsis-svd/cmsis-svd-data"
lib_path="lib/cmsis-svd"
git_hash="05a9562ec59b87945a8d7177a4b08b7aa2f2fd58"
tasks=(
"-source=https://github.com/posborne/cmsis-svd/tree/master/data/Kendryte-Community -interrupts=software lib/cmsis-svd/data/Kendryte-Community/"
)
ignore_list=""
target="device/kendryte"
generator="gen-device-svd"
}

declare_stm32_config() {
name="stm32"
repo="https://github.com/tinygo-org/stm32-svd"
lib_path="lib/stm32-svd"
git_hash="e6db8e32d5d42293a528434ec12e7f88479a8649"
tasks=(
"-source=https://github.com/tinygo-org/stm32-svd lib/stm32-svd/svd"
)
ignore_list=""
target="device/stm32"
generator="gen-device-svd"
}

declare_rp_config() {
name="rp"
repo="https://github.com/cmsis-svd/cmsis-svd-data"
lib_path="lib/cmsis-svd"
git_hash="05a9562ec59b87945a8d7177a4b08b7aa2f2fd58"
tasks=(
"-source=https://github.com/posborne/cmsis-svd/tree/master/data/RaspberryPi lib/cmsis-svd/data/RaspberryPi/"
)
ignore_list="rp2040-extra.go rp2350-extra.go"
target="device/rp"
generator="gen-device-svd"
}

declare_renesas_config() {
name="renesas"
repo="https://github.com/cmsis-svd/cmsis-svd-data"
lib_path="lib/cmsis-svd"
git_hash="05a9562ec59b87945a8d7177a4b08b7aa2f2fd58"
tasks=(
"-source=https://github.com/cmsis-svd/cmsis-svd-data/tree/master/data/Renesas lib/cmsis-svd/data/Renesas/"
)
ignore_list=""
target="device/renesas"
generator="gen-device-svd"
}

# List of device configuration functions
DEVICE_CONFIGS=(
"declare_avr_config"
"declare_esp_config"
"declare_nrf_config"
"declare_nxp_config"
"declare_sam_config"
"declare_sifive_config"
"declare_kendryte_config"
"declare_stm32_config"
"declare_rp_config"
"declare_renesas_config"
)

# Generate device files from all tasks to specified directory
generate_device_files() {
local device_name="$1"
shift
local generator="${@: -2:1}"
local target_dir="${@: -1}"
# Remove generator and target_dir from args to get tasks
set -- "${@:1:$#-2}"
local tasks_array=("$@")

echo "[$device_name] Processing ${#tasks_array[@]} tasks..."
for task in "${tasks_array[@]}"; do
echo "[$device_name] Processing task: $task"
"$generator" $task "$target_dir/"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security: Potential Command Injection

The $task variable is expanded without proper quoting. While the current hardcoded values are safe, this pattern is risky.

Recommendation:
Use proper quoting or restructure to avoid word splitting:

"$generator" "$task" "$target_dir/"

echo "[$device_name] Generated to $target_dir"
done
echo "[$device_name] All tasks processed successfully"

# Format Go files in target directory
echo "[$device_name] Formatting Go files in $target_dir..."
(cd "$target_dir" && GO111MODULE=off ${GO:-go} fmt .)
echo "[$device_name] Go formatting completed"
}

# Generate devices for a specific device configuration
generate_devices() {
local config_func="$1"
local mode="$2"

# Call the configuration function to set variables
$config_func

# Validate configuration
if [[ -z "$repo" || -z "$lib_path" || -z "$git_hash" || -z "$generator" || -z "$target" || ${#tasks[@]} -eq 0 ]]; then
echo "Error: Missing configuration for device '$name'"
return 1
fi

# Use target directory from configuration
local target_dir="$target"
case "$mode" in
generate)
echo "[$name] Running in generation mode - will clean and generate to $target_dir"
;;
verify)
echo "[$name] Running in verification mode - will verify generated content matches $target_dir"
;;
*)
echo "[$name] Running in default mode - will generate to $target_dir"
;;
esac

# Clone and setup repository
echo "[$name] Setting up repository..."
rm -rf "$lib_path"
git clone "$repo" "$lib_path"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performance: Sequential Git Operations (Critical Bottleneck)

Git clone operations run sequentially for all 10 devices, wasting 100-600 seconds. Additionally, 7 devices share the same cmsis-svd-data repository but clone it separately (~350MB+ redundant transfers).

Recommendations:

  1. Use shallow clones: git clone --depth 1
  2. Share repository clones between devices that use the same repo
  3. Parallelize device generation with background jobs

cd "$lib_path"
git checkout "$git_hash"
cd ../../

# Create target directory
mkdir -p "$target_dir"

# Handle verification mode
if [ "$mode" = "verify" ]; then
echo "[$name] Starting verification process..."

# Check if target directory exists and has content
if [ ! -d "$target_dir" ] || [ -z "$(ls -A "$target_dir" 2>/dev/null)" ]; then
echo "[$name] Verification failed: target directory is empty or does not exist"
return 1
fi

# Create temporary directory with same structure
temp_target=".verify/$target"
echo "[$name] Creating temporary directory: $temp_target"
mkdir -p "$temp_target"

# Generate files to temporary directory
echo "[$name] Generating files to temporary directory..."
generate_device_files "$name" "${tasks[@]}" "$generator" "$temp_target"

# Copy ignore list files to temporary directory
if [ -n "$ignore_list" ]; then
echo "[$name] Copying ignore list files to temporary directory: $ignore_list"
for file in $ignore_list; do
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The ignore_list variable is treated as a space-separated string, which will cause issues if any of the filenames in the list contain spaces. It's more robust to define ignore_list as a bash array in the declare_*_config functions and iterate over it correctly.

For example, in declare_avr_config:

ignore_list=("avr.go" "avr_tiny85.go")

And then in generate_devices, you should iterate over it like this:

for file in "${ignore_list[@]}"; do

This change should be applied to all declare_*_config functions and all loops that iterate over ignore_list (lines 237, 268, 279). Also, checks for non-empty list should be changed from if [ -n "$ignore_list" ] to if [ ${#ignore_list[@]} -gt 0 ] (lines 235, 261).

if [ -f "$target_dir/$file" ]; then
cp "$target_dir/$file" "$temp_target/"
echo "[$name] Copied: $file"
fi
done
fi

# Compare directories
echo "[$name] Comparing original directory with generated directory..."
if diff -u -r "$target_dir" "$temp_target" > /dev/null 2>&1; then
echo "[$name] Verification passed: generated files match existing files"
VERIFY_RESULT=0
else
echo "[$name] Verification failed: differences found"
echo "[$name] Detailed differences:"
diff -u -r "$target_dir" "$temp_target" || true
VERIFY_RESULT=1
fi

return $VERIFY_RESULT
fi

# Clean target directory if in generation mode
if [ "$mode" = "generate" ]; then
echo "[$name] Cleaning $target_dir"

# Backup ignored files if ignore_list is not empty
if [ -n "$ignore_list" ]; then
echo "[$name] Preserving ignore list: $ignore_list"
# Create temp directory to store ignored files
TEMP_DIR=$(mktemp -d)

# Backup ignored files if they exist
for file in $ignore_list; do
if [ -f "$target_dir/$file" ]; then
cp "$target_dir/$file" "$TEMP_DIR/"
echo "[$name] Backed up: $file"
fi
done
fi

# Remove all files from target directory
rm -rf "$target_dir"/*
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Quality: Unsafe Glob Deletion

If $target_dir is empty or manipulated, this could delete unintended files.

Recommendation:

if [ -z "$target_dir" ] || [ "$target_dir" = "/" ]; then
    echo "[$name] Error: Invalid target directory"
    return 1
fi
rm -rf "${target_dir:?}"/*


# Restore ignored files if ignore_list is not empty
if [ -n "$ignore_list" ]; then
for file in $ignore_list; do
if [ -f "$TEMP_DIR/$file" ]; then
cp "$TEMP_DIR/$file" "$target_dir/"
echo "[$name] Restored: $file"
fi
done

# Clean up temp directory
rm -rf "$TEMP_DIR"
fi
fi

# Generate device files from all tasks
generate_device_files "$name" "${tasks[@]}" "$generator" "$target_dir"
}

# Parse command line arguments
MODE=""
case "$1" in
generate)
MODE="generate"
;;
verify)
MODE="verify"
;;
*)
MODE="default"
;;
esac

# Initialize verification tracking
VERIFICATION_FAILED=0

# Process all enabled devices
for config_func in "${DEVICE_CONFIGS[@]}"; do
if ! generate_devices "$config_func" "$MODE"; then
if [ "$MODE" = "verify" ]; then
VERIFICATION_FAILED=1
fi
fi
done

if [ "$MODE" = "verify" ]; then
if [ $VERIFICATION_FAILED -eq 0 ]; then
echo "All device verifications passed"
else
echo "Device verification failed: inconsistencies found"
exit 1
fi
else
echo "All device generations completed!"
fi
Loading