Skip to content

Commit

Permalink
Merge pull request #1 from rbs-jacob/feature/ppc-vle-automation
Browse files Browse the repository at this point in the history
Add automatic toolchain download
  • Loading branch information
paulnoalhyt committed Jun 28, 2023
2 parents ba1ad0e + 72e2fbc commit 61a4675
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 9 deletions.
12 changes: 10 additions & 2 deletions .github/workflows/test-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,12 @@ jobs:
- name: Build base image
# Always rebuild the base image when the scheduled workflow runs
if: inputs.flush_cache || steps.cache-image.outputs.cache-hit != 'true' || github.event_name == 'schedule'
env:
NXP_EMAIL: ${{ secrets.NXP_EMAIL }}
NXP_PASSWORD: ${{ secrets.NXP_PASSWORD }}
run: |
python3 -m pip install PyYAML
DOCKER_BUILDKIT=1 python3 build_image.py --config ofrak-core-dev.yml --base
DOCKER_BUILDKIT=1 python3 build_image.py --config ofrak-core-dev.yml --base --nxp-email "${NXP_EMAIL}" --nxp-password "${NXP_PASSWORD}"
- name: Export base image
if: inputs.flush_cache || steps.cache-image.outputs.cache-hit != 'true' || github.event_name == 'schedule'
run: |
Expand Down Expand Up @@ -113,14 +116,19 @@ jobs:
| docker load
docker images
- name: Build Ghidra image
env:
NXP_EMAIL: ${{ secrets.NXP_EMAIL }}
NXP_PASSWORD: ${{ secrets.NXP_PASSWORD }}
run: |
python3 -m pip install PyYAML
DOCKER_BUILDKIT=1 \
python3 build_image.py \
--config ofrak-ghidra.yml \
--base \
--finish \
--cache-from redballoonsecurity/ofrak/core-dev-base:latest
--cache-from redballoonsecurity/ofrak/core-dev-base:latest \
--nxp-email "${NXP_EMAIL}" \
--nxp-password "${NXP_PASSWORD}"
- name: Test documentation
run: |
docker run \
Expand Down
29 changes: 29 additions & 0 deletions build_image.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import tempfile
from dataclasses import dataclass
from enum import Enum
from typing import List, Optional
Expand Down Expand Up @@ -35,6 +36,8 @@ class OfrakImageConfig:
install_target: InstallTarget
cache_from: List[str]
entrypoint: Optional[str]
nxp_email: Optional[str]
nxp_password: Optional[str]

def validate_serial_txt_existence(self):
"""
Expand Down Expand Up @@ -81,11 +84,27 @@ def main():
for cache in config.cache_from:
cache_args.append("--cache-from")
cache_args.append(cache)
nxp_args = []
email_file = password_file = None
if config.nxp_email and config.nxp_password:
email_file = tempfile.NamedTemporaryFile(suffix=".txt", mode="w+")
email_file.write(config.nxp_email)
email_file.flush()
password_file = tempfile.NamedTemporaryFile(suffix=".txt", mode="w+")
password_file.write(config.nxp_password)
password_file.flush()
nxp_args = [
"--secret",
f"id=nxp_email,src={email_file.name}",
"--secret",
f"id=nxp_password,src={password_file.name}",
]
base_command = [
"docker",
"build",
"--build-arg",
"BUILDKIT_INLINE_CACHE=1",
*nxp_args,
"--cache-from",
f"{full_base_image_name}:master",
*cache_args,
Expand All @@ -108,6 +127,9 @@ def main():
print(f"Error running command: '{' '.join(error.cmd)}'")
print(f"Exit status: {error.returncode}")
sys.exit(error.returncode)
if email_file and password_file:
email_file.close()
password_file.close()

if config.build_finish:
full_image_name = "/".join((config.registry, config.image_name))
Expand Down Expand Up @@ -146,7 +168,12 @@ def parse_args() -> OfrakImageConfig:
default=InstallTarget.DEVELOP.value,
)
parser.add_argument("--cache-from", action="append")
parser.add_argument("--nxp-email")
parser.add_argument("--nxp-password")
args = parser.parse_args()
if (not not args.nxp_email) ^ (not not args.nxp_password):
raise RuntimeError("Must include the NXP email and password!")

with open(args.config) as file_handle:
config_dict = yaml.safe_load(file_handle)
image_config = OfrakImageConfig(
Expand All @@ -161,6 +188,8 @@ def parse_args() -> OfrakImageConfig:
InstallTarget(args.target),
args.cache_from,
config_dict.get("entrypoint"),
args.nxp_email,
args.nxp_password,
)
image_config.validate_serial_txt_existence()
return image_config
Expand Down
17 changes: 10 additions & 7 deletions ofrak_patch_maker/Dockerstub
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,19 @@ RUN if [ "$TARGETARCH" = "amd64" ]; then \
fi;

#PPCVLE 4 NXP GCC Fork
# Download the toolchain into your OFRAK directory from here (requires sign up):
# https://www.nxp.com/design/software/development-software/s32-design-studio-ide/s32-design-studio-for-power-architecture:S32DS-PA
# if the file `gcc-4.9.4-Ee200-eabivle-x86_64-linux-g2724867.zip` doesn't exist, the toolchain won't be installed, and corresponding tests will be skipped.
# Only runs if the NXP email and password to log in and download the toolchain are passed to build_image.py via the CLI flags
ARG OFRAK_DIR=.
COPY $OFRAK_DIR/gcc-4.9.4-Ee200-eabivle-x86_64-linux-g2724867.zi[p] /tmp
RUN test -f /tmp/gcc-4.9.4-Ee200-eabivle-x86_64-linux-g2724867.zip && \
COPY $OFRAK_DIR/ofrak_patch_maker/download_ppcvle.py /tmp/
RUN --mount=type=secret,id=nxp_email,dst=/tmp/nxp_email.txt \
--mount=type=secret,id=nxp_password,dst=/tmp/nxp_password.txt \
test -f /tmp/nxp_email.txt && \
test -f /tmp/nxp_password.txt && \
python3 -m pip install playwright && \
playwright install --with-deps chromium && \
python3 /tmp/download_ppcvle.py "$(cat /tmp/nxp_email.txt)" "$(cat /tmp/nxp_password.txt)" && \
cd /tmp && \
unzip -q gcc-4.9.4-Ee200-eabivle-x86_64-linux-g2724867.zip && \
cp -r powerpc-eabivle-4_9 /opt/rbs/toolchain/ && \
rm -rf powerpc-eabivle-4_9 && \
mv powerpc-eabivle-4_9 /opt/rbs/toolchain/ && \
rm gcc-4.9.4-Ee200-eabivle-x86_64-linux-g2724867.zip && \
dpkg --add-architecture i386 && \
apt-get update && \
Expand Down
53 changes: 53 additions & 0 deletions ofrak_patch_maker/download_ppcvle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import argparse
import os

from playwright.sync_api import sync_playwright


START_URL = "https://www.nxp.com/design/software/development-software/s32-design-studio-ide/s32-design-studio-for-power-architecture:S32DS-PA"


def run(page, email: str, password: str, outfile: str) -> None:
print(f"Going to page {START_URL}", flush=True)
page.goto(START_URL)
page.get_by_role("listitem").filter(
has_text="Build Tools NXP Embedded GCC for Power Architecture"
).filter(has_text="Linux").get_by_role("link", name="Download", exact=True).click()

print("Signing in", flush=True)
page.locator("#username").click()
page.keyboard.type(email)
page.locator("#password").click()
page.keyboard.type(password)
page.get_by_role("button", name="SIGN IN").click()

print("Accepting terms and conditions", flush=True)
page.get_by_role("button", name="I Accept").click()

print("Waiting for download", flush=True)
with page.expect_download() as download_info:
# Download begins when the page is loaded
pass
os.rename(download_info.value.path(), outfile)

print(f"Complete! Saved to {outfile}", flush=True)


def main(args):
with sync_playwright() as playwright:
browser = playwright.chromium.launch(headless=True)
context = browser.new_context()
page = context.new_page()
run(page, args.email, args.password, args.outfile)
context.close()
browser.close()


if __name__ == "__main__":
argument_parser = argparse.ArgumentParser()
argument_parser.add_argument("email")
argument_parser.add_argument("password")
argument_parser.add_argument(
"-o", "--outfile", default="/tmp/gcc-4.9.4-Ee200-eabivle-x86_64-linux-g2724867.zip"
)
main(argument_parser.parse_args())

0 comments on commit 61a4675

Please sign in to comment.