Skip to content

Commit

Permalink
Merge pull request #477 from ZuluSCSI/feature/common-file-update
Browse files Browse the repository at this point in the history
Use single firmware bundle for updating all ZuluSCSI platforms
  • Loading branch information
aperezbios authored Dec 2, 2024
2 parents 071572c + 4e1f529 commit f9cc823
Show file tree
Hide file tree
Showing 13 changed files with 524 additions and 21 deletions.
46 changes: 28 additions & 18 deletions .github/workflows/firmware_build.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Build ZuluSCSI firmware

on:
on:
push:
workflow_dispatch:
pull_request:
Expand All @@ -11,46 +11,56 @@ jobs:
# runs-on: self-hosted
name: Build firmware on GitHub using latest Ubuntu
runs-on: ubuntu-latest

steps:
- name: Check out code from GitHub
uses: actions/checkout@v4
with:
path: ZuluSCSI
fetch-depth: "0"


- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install zip
- name: Install platformio
run: |
pip install -U platformio
- name: Build firmware
run: |
cd ZuluSCSI
pio run -v -j8
- name: Rename firmware files
run: |
cd ZuluSCSI
utils/rename_binaries.sh
- name: Create bin package zip file
run: |
cd ZuluSCSI
utils/create_bin_package_zip.sh
- name: Upload binaries into build artifacts
uses: actions/upload-artifact@v4
with:
path: ZuluSCSI/distrib/*
name: ZuluSCSI binaries
# - name: Upload to latest release
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# if: github.ref == 'refs/heads/main'
# run: |
# cd ZuluSCSI
# git tag -d latest
# git tag latest
# git push origin --force latest
# cd distrib
# gh api repos/${GITHUB_REPOSITORY}/releases/tags/latest | jq -r '.assets[] | [.url] | @tsv' | xargs -n 1 gh api -X DELETE || true
# gh release upload --repo ${GITHUB_REPOSITORY} --clobber latest *

- name: Upload to latest release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: github.ref == 'refs/heads/main'
run: |
cd ZuluSCSI
git tag -d latest
git tag latest
git push origin --force latest
cd distrib
gh api repos/${GITHUB_REPOSITORY}/releases/tags/latest | jq -r '.assets[] | [.url] | @tsv' | xargs -n 1 gh api -X DELETE || true
gh release upload --repo ${GITHUB_REPOSITORY} --clobber latest *
- name: Upload to newly created release
env:
Expand Down
241 changes: 241 additions & 0 deletions lib/ZipParser/zip_parser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
/**
* ZuluSCSI™ - Copyright (c) 2024 Rabbit Hole Computing™
*
* ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
*
* https://www.gnu.org/licenses/gpl-3.0.html
* ----
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. 
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details. 
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <https://www.gnu.org/licenses/>.
**/

#include "zip_parser.h"

#define ZIP_PARSER_METHOD_DEFLATE_BYTE 0x08
#define ZIP_PARSER_METHOD_UNCOMPRESSED_BYTE 0x00

namespace zipparser
{

Parser::Parser()
{
filename_len = 0;
Reset();
}
Parser::Parser(char const *filename, const size_t length)
{
Reset();
SetMatchingFilename(filename, length);
}

void Parser::Reset()
{
target = parsing_target::signature;
position = 0;
filename_match = false;
crc = 0;
}

void Parser::SetMatchingFilename(char const *filename, const size_t length)
{
if (filename[0] == '\0')
filename_len = 0;
else
{
this->filename = filename;
filename_len = length;
}
}


int32_t Parser::Parse(uint8_t const *buf, const size_t size)
{
if (filename_len == 0)
return PARSE_ERROR;

static bool matching = true;
static bool central_dir = false;
static bool local_file_header = false;
for (size_t idx = 0; idx < size; idx++)
{
switch (target)
{
case parsing_target::signature:
if (++position == 1 && buf[idx] == 'P')
break;
if (position == 2 && buf[idx] == 'K')
{
local_file_header = false;
central_dir = false;
break;
}
if (position == 3 && buf[idx] == 0x03)
{
local_file_header = true;
break;
}
if (position == 3 && buf[idx] == 0x01)
{
central_dir = true;
break;
}
if (central_dir && position == 4 && buf[idx] == 0x2)
{
return PARSE_CENTRAL_DIR;
}
if (local_file_header && position == 4 && buf[idx] == 0x04)
{
position = 0;
target = parsing_target::version;
break;
}
return PARSE_ERROR;
break;
case parsing_target::version:
if (++position == 2)
{
position = 0;
target = parsing_target::flag;
}
break;
case parsing_target::flag:
if (++position == 2)
{
position = 0;
target = parsing_target::method;
}
break;
case parsing_target::method:
if (++position == 1)
{
// Currently only uncompresseed files in the zip package are supported
if (!buf[idx] == ZIP_PARSER_METHOD_UNCOMPRESSED_BYTE)
{
return PARSE_UNSUPPORTED_COMPRESSION;
}
}
if (position == 2)
{
if (buf[idx] == 0)
{
position = 0;
target = parsing_target::modify_time;
}
else
return PARSE_UNSUPPORTED_COMPRESSION;
}
break;
case parsing_target::modify_time:
if (++position == 2)
{
position = 0;
target = parsing_target::modify_date;
}
break;
case parsing_target::modify_date:
if (++position == 2)
{
position = 0;
target = parsing_target::crc;
crc = 0;
}
break;
case parsing_target::crc:
crc |= buf[idx] << (8 * position++);
if (position == 4)
{
target = parsing_target::size_compressed;
compressed_data_size = 0;
position = 0;
}
break;
case parsing_target::size_compressed:
compressed_data_size |= buf[idx] << (8 * position++);
if (position == 4)
{
target = parsing_target::size_uncompressed;
uncompressed_data_size = 0;
position = 0;
}
break;
case parsing_target::size_uncompressed:
uncompressed_data_size |= buf[idx] << (8 * position++);
if (position == 4)
{
target = parsing_target::filename_len;
current_zip_filename_len = 0;
position = 0;
}
break;
case parsing_target::filename_len:
current_zip_filename_len |= buf[idx] << (8 * position++);
if (position == 2)
{
target = parsing_target::extra_field_len;
extra_field_len = 0;
position = 0;
}
break;
case parsing_target::extra_field_len:
extra_field_len |= buf[idx] << (8 * position++);
if (position == 2)
{
target = parsing_target::filename;
position = 0;
filename_match = false;
matching = true;
}
break;
case parsing_target::filename:
if (position <= current_zip_filename_len - 1)
{
if (matching && position < filename_len && filename[position] != buf[idx])
matching = false;
if (position == filename_len - 1 && matching)
filename_match = true;
if (position == current_zip_filename_len -1)
{
target = parsing_target::extra_field;
matching = true;
position = 0;
if (extra_field_len == 0)
{
target = parsing_target::end;
return idx + 1;
}
}
else
position++;
}
break;
case parsing_target::extra_field:
// extra_field_len should be at least 1 by this time
if (++position == extra_field_len)
{
target = parsing_target::end;
return idx + 1;
}
break;
case parsing_target::end:
return 0;
break;
}
}
return size;
}
bool Parser::FoundMatch()
{
return filename_match;
}
}

63 changes: 63 additions & 0 deletions lib/ZipParser/zip_parser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* ZuluSCSI™ - Copyright (c) 2024 Rabbit Hole Computing™
*
* ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
*
* https://www.gnu.org/licenses/gpl-3.0.html
* ----
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. 
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details. 
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <https://www.gnu.org/licenses/>.
**/

#pragma once

#include <stdint.h>
#include <strings.h>
namespace zipparser
{
enum class parsing_target {signature, version, flag, method, modify_time, modify_date,
crc, size_compressed, size_uncompressed, filename_len,
extra_field_len, filename, extra_field, end};

class Parser
{
public:
Parser();
Parser(char const *filename, const size_t length);
void SetMatchingFilename(char const *filename, const size_t length);
void Reset();
static const int32_t PARSE_ERROR = -1;
static const int32_t PARSE_CENTRAL_DIR = -2;
static const int32_t PARSE_UNSUPPORTED_COMPRESSION = -3;
// A state machine that per byte processes the incoming buffer
// \param buf a pointer to binary data to be processed
// \param size of data to be processed, can by 1 for a single byte at a time
// \returns the number of bytes processed or -1 if an error ocurred
int32_t Parse(uint8_t const *buf, const size_t size);
bool FoundMatch();
inline uint32_t GetCompressedSize() {return compressed_data_size;}

protected:
bool filename_match;
char const *filename;
size_t filename_len;
size_t current_zip_filename_len;
size_t extra_field_len;
uint32_t compressed_data_size;
uint32_t uncompressed_data_size;
parsing_target target;
size_t position;
uint32_t crc;

};
}
Loading

0 comments on commit f9cc823

Please sign in to comment.