commit 3b211f6e54f7b6f766b8649c9cf88c2f73a00b82 Author: Maschell Date: Sun Dec 26 09:13:58 2021 +0100 first commit diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5e6a39b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,65 @@ +name: CI-Release + +on: + push: + branches: + - main + +jobs: + + build-binary: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - name: Checkout submodules using a PAT + run: | + git config --file .gitmodules --get-regexp url | while read url; do + git config --file=.gitmodules $(echo "$url" | sed -E "s/git@github.com:|https:\/\/github.com\//https:\/\/${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com\//") + done + git submodule sync + git submodule update --init --recursive + - name: build binary + run: | + docker build . -t builder + docker run --rm -v ${PWD}:/project builder make + - uses: actions/upload-artifact@master + with: + name: binary + path: "*.rpx" + deploy-binary: + needs: build-binary + runs-on: ubuntu-18.04 + steps: + - name: Get environment variables + id: get_repository_name + run: | + echo REPOSITORY_NAME=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}' | sed -e "s/:refs//") >> $GITHUB_ENV + echo DATETIME=$(echo $(date '+%Y%m%d-%H%M%S')) >> $GITHUB_ENV + - uses: actions/download-artifact@master + with: + name: binary + - name: zip artifact + run: zip -r ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip *.rpx + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }} + release_name: Nightly-${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }} + draft: false + prerelease: true + body: | + Not a stable release: + ${{ github.event.head_commit.message }} + - name: Upload Release Asset + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + asset_path: ./${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip + asset_name: ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip + asset_content_type: application/unknown \ No newline at end of file diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 0000000..8e28a5f --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,24 @@ +name: CI-PR + +on: [pull_request] + +jobs: + build-binary: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - name: Checkout submodules using a PAT + run: | + git config --file .gitmodules --get-regexp url | while read url; do + git config --file=.gitmodules $(echo "$url" | sed -E "s/git@github.com:|https:\/\/github.com\//https:\/\/${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com\//") + done + git submodule sync + git submodule update --init --recursive + - name: build binary + run: | + docker build . -t builder + docker run --rm -v ${PWD}:/project builder make + - uses: actions/upload-artifact@master + with: + name: binary + path: "*.rpx" \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..698dbae --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*.elf +*.rpx +build/ +*.cbp +obj/ +relocator.h +*.depend +*.cscope_file_list +*.layout +.idea/ +cmake-build-debug/ +*.txt +build1/ +cmake-build-default/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..fff8062 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "homebrew_launcher_installer"] + path = homebrew_launcher_installer + url = https://github.com/wiiu-env/homebrew_launcher_installer diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1fcc684 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,3 @@ +FROM wiiuenv/devkitppc:20211106 + +WORKDIR project \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4a17a6e --- /dev/null +++ b/Makefile @@ -0,0 +1,146 @@ +#------------------------------------------------------------------------------- +.SUFFIXES: +#------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") +endif + +TOPDIR ?= $(CURDIR) + +include $(DEVKITPRO)/wut/share/wut_rules + +#------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +#------------------------------------------------------------------------------- +TARGET := 50_hbl_installer +BUILD := build +SOURCES := source +DATA := data +INCLUDES := source + +#------------------------------------------------------------------------------- +# options for code generation +#------------------------------------------------------------------------------- +CFLAGS := -g -Wall -O3 -ffunction-sections -fno-exceptions -fno-rtti\ + $(MACHDEP) + +CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ + +CXXFLAGS := $(CFLAGS) -std=c++20 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) + +LIBS := -lwut -lz + +#------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level +# containing include and lib +#------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(WUT_ROOT) + +#------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#------------------------------------------------------------------------------- + export LD := $(CC) +#------------------------------------------------------------------------------- +else +#------------------------------------------------------------------------------- + export LD := $(CXX) +#------------------------------------------------------------------------------- +endif +#------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) payload.elf.o +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +.PHONY: $(BUILD) clean all + +#------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + make -C homebrew_launcher_installer + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#------------------------------------------------------------------------------- +clean: + @echo clean ... + make clean -C homebrew_launcher_installer + @rm -fr $(BUILD) $(TARGET).rpx $(TARGET).elf + +#------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#------------------------------------------------------------------------------- +# main targets +#------------------------------------------------------------------------------- + +hbl_installer_payload := ../homebrew_launcher_installer/payload.elf + +all : $(OUTPUT).rpx + +$(hbl_installer_payload): + make -C ../homebrew_launcher_installer + +$(OUTPUT).rpx : $(OUTPUT).elf +$(OUTPUT).elf : $(OFILES) +$(OFILES) : hbl_installer_payload.h + +$(OFILES_SRC) : $(HFILES_BIN) + +#------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#------------------------------------------------------------------------------- +hbl_installer_payload.h: $(hbl_installer_payload) + @bin2s -a 32 -H `(echo $( $@ + @printf '#include "' >> $@ + @(printf $(> $@ + @echo '.h"' >> $@ + @printf '#define PAYLOAD_HASH "' >> $@ + @sha1sum $(<) | cut -f1 -d' ' | tr -d '\n' >> $@ + @printf '"' >> $@ + +#------------------------------------------------------------------------------- +endif +#------------------------------------------------------------------------------- diff --git a/README.md b/README.md new file mode 100644 index 0000000..429630f --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# Homebrew launcher wrapper payload +A simple wrapper that is just executing [homebrew_launcher_installer](https://github.com/wiiu-env/homebrew_launcher_installer). + +## Usage +Place the `50_hbl_installer.rpx` in the `[ENVIROMENT]/modules/setup` folder and run the [EnvironmentLoader](https://github.com/wiiu-env/EnvironmentLoader). +Requires [MochaPayload](https://github.com/wiiu-env/MochaPayload) as a setup module in `[ENVIROMENT]/modules/setup` when coldbooting. +Read the intructions in the [original repo](https://github.com/wiiu-env/homebrew_launcher_installer) for further usage. +TLDR: Put the [homebrew_launcher.elf](https://github.com/dimok789/homebrew_launcher) in `sd:/wiiu/apps/homebrew_launcher/homebrew_launcher.elf`. When coldbooting you need to open the Mii Maker to start it. + +## Building + +For building you just need [wut](https://github.com/devkitPro/wut/) installed, then use the `make` command. + +## Building using the Dockerfile + +It's possible to use a docker image for building. This way you don't need anything installed on your host system. + +``` +# Build docker image (only needed once) +docker build . -t hblinstallerwrapper-builder + +# make +docker run -it --rm -v ${PWD}:/project hblinstallerwrapper-builder make + +# make clean +docker run -it --rm -v ${PWD}:/project hblinstallerwrapper-builder make clean +``` + +## Credits +See [homebrew_launcher_installer](https://github.com/wiiu-env/homebrew_launcher_installer) \ No newline at end of file diff --git a/homebrew_launcher_installer b/homebrew_launcher_installer new file mode 160000 index 0000000..a3d477f --- /dev/null +++ b/homebrew_launcher_installer @@ -0,0 +1 @@ +Subproject commit a3d477f1a3d1cc06d89574ee1cc047eb2c90ed7a diff --git a/source/crt.c b/source/crt.c new file mode 100644 index 0000000..2fcd925 --- /dev/null +++ b/source/crt.c @@ -0,0 +1,36 @@ +void __init_wut_malloc(); + +void __init_wut_newlib(); + +void __init_wut_stdcpp(); + +void __init_wut_devoptab(); + +void __attribute__((weak)) __init_wut_socket(); + +void __fini_wut_malloc(); + +void __fini_wut_newlib(); + +void __fini_wut_stdcpp(); + +void __fini_wut_devoptab(); + +void __attribute__((weak)) __fini_wut_socket(); + +void __attribute__((weak)) +__init_wut_() { + __init_wut_malloc(); + __init_wut_newlib(); + __init_wut_stdcpp(); + __init_wut_devoptab(); + if (&__init_wut_socket) __init_wut_socket(); +} + +void __attribute__((weak)) +__fini_wut_() { + __fini_wut_devoptab(); + __fini_wut_stdcpp(); + __fini_wut_newlib(); + __fini_wut_malloc(); +} diff --git a/source/crt0.s b/source/crt0.s new file mode 100644 index 0000000..318de30 --- /dev/null +++ b/source/crt0.s @@ -0,0 +1,29 @@ +.extern main +.extern exit +.extern __init_wut_ +.extern __fini_wut_ + +.global _start +_start: + stwu 1, -0x28(1) + mflr 0 + stw 0, 0x2C(1) + stw 31, 0x24(1) + or 31, 1, 1 + stw 3, 0x18(31) + stw 4, 0x1C(31) + bl __init_wut_ + lwz 4, 0x1C(31) + lwz 3, 0x18(31) + bl main + or 9, 3, 3 + stw 9, 0x8(31) + bl __fini_wut_ + lwz 9, 0x8(31) + or 3, 9, 9 + addi 11, 31, 0x28 + lwz 0, 0x4(11) + mtlr 0 + lwz 31, -0x4(11) + or 1, 11, 11 + blr \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp new file mode 100644 index 0000000..fb57fc4 --- /dev/null +++ b/source/main.cpp @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include +#include "../homebrew_launcher_installer/src/elf_abi.h" +#include "payload_elf.h" + +static unsigned int load_elf_image (const uint8_t* elfstart) { + Elf32_Ehdr *ehdr; + Elf32_Phdr *phdrs; + unsigned char *image; + int i; + + ehdr = (Elf32_Ehdr *) elfstart; + + if(ehdr->e_phoff == 0 || ehdr->e_phnum == 0) + return 0; + + if(ehdr->e_phentsize != sizeof(Elf32_Phdr)) + return 0; + + phdrs = (Elf32_Phdr*)(elfstart + ehdr->e_phoff); + + for(i = 0; i < ehdr->e_phnum; i++) { + if(phdrs[i].p_type != PT_LOAD) + continue; + + if(phdrs[i].p_filesz > phdrs[i].p_memsz) + continue; + + if(!phdrs[i].p_filesz) + continue; + + unsigned int p_paddr = phdrs[i].p_paddr; + image = (unsigned char *) (elfstart + phdrs[i].p_offset); + + memcpy ((void *) p_paddr, image, phdrs[i].p_filesz); + DCFlushRange((void*)p_paddr, phdrs[i].p_filesz); + + if(phdrs[i].p_flags & PF_X) + ICInvalidateRange ((void *) p_paddr, phdrs[i].p_memsz); + } + + //! clear BSS + Elf32_Shdr *shdr = (Elf32_Shdr *) (elfstart + ehdr->e_shoff); + for(i = 0; i < ehdr->e_shnum; i++) { + const char *section_name = ((const char*)elfstart) + shdr[ehdr->e_shstrndx].sh_offset + shdr[i].sh_name; + if(section_name[0] == '.' && section_name[1] == 'b' && section_name[2] == 's' && section_name[3] == 's') { + memset((void*)shdr[i].sh_addr, 0, shdr[i].sh_size); + DCFlushRange((void*)shdr[i].sh_addr, shdr[i].sh_size); + } else if(section_name[0] == '.' && section_name[1] == 's' && section_name[2] == 'b' && section_name[3] == 's' && section_name[4] == 's') { + memset((void*)shdr[i].sh_addr, 0, shdr[i].sh_size); + DCFlushRange((void*)shdr[i].sh_addr, shdr[i].sh_size); + } + } + + return ehdr->e_entry; +} + +int main(int argc, char **argv) { + uint32_t res = load_elf_image(payload_elf); + if(res != 0) { + ((int (*)(int, char **)) res)(0, nullptr); + } + + return 0; +}