commit 8f46eb434bf9d6547acb59e5cd1eb1fe2812be16 Author: Maschell Date: Sun Nov 29 12:59:58 2020 +0100 first commit diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..acee0dc --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,58 @@ +name: CI-Release + +on: + push: + branches: + - master + +jobs: + build-binary: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - 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: "payload.elf" + 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 + path: wiiu + - name: zip artifact + run: zip -r ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip wiiu + - 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..e652ab1 --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,17 @@ +name: CI-PR + +on: [pull_request] + +jobs: + build-binary: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - 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: "*.elf" \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..da5a916 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +/*.elf +/*.cbp +/build +*.rpx +*.bin +*.cscope_file_list +*.layout +cmake-build-debug/ +.idea/ +CMakeLists.txt diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9d90502 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,3 @@ +FROM wiiuenv/devkitppc:20200810 + +WORKDIR project \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..23cb790 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + 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 2 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..53226ba --- /dev/null +++ b/Makefile @@ -0,0 +1,212 @@ +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPRO") +endif +export PATH := $(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH) +export PORTLIBS := $(DEVKITPRO)/portlibs/ppc + +GCC_VER := $(shell $(DEVKITPPC)/bin/powerpc-eabi-gcc -dumpversion) + +PREFIX := powerpc-eabi- + +export AS := $(PREFIX)as +export CC := $(PREFIX)gcc +export CXX := $(PREFIX)g++ +export AR := $(PREFIX)ar +export OBJCOPY := $(PREFIX)objcopy + +#--------------------------------------------------------------------------------- +# 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 +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := payload +BUILD := build +BUILD_DBG := $(TARGET)_dbg +SOURCES := src \ + src/utils + +DATA := data + +INCLUDES := src + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +CFLAGS := -std=c2x -g -Wall -O2 -ffunction-sections -DESPRESSO -mcpu=750 -meabi -mhard-float $(INCLUDE) +CXXFLAGS := -std=c++20 -g -Wall -O2 -ffunction-sections -DESPRESSO -mcpu=750 -meabi -mhard-float $(INCLUDE) +ASFLAGS := -mregnames +LDFLAGS := -nostartfiles -Wl,--gc-sections,--allow-multiple-definition + +#--------------------------------------------------------------------------------- +Q := @ +MAKEFLAGS += --no-print-directory +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -lwut + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(CURDIR) \ + $(DEVKITPPC)/lib \ + $(DEVKITPRO)/wut \ + $(DEVKITPPC)/lib/gcc/powerpc-eabi/$(GCC_VER) + + +#--------------------------------------------------------------------------------- +# 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 PROJECTDIR := $(CURDIR) +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +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 := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ + $(sFILES:.s=.o) $(SFILES:.S=.o) \ + $(PNGFILES:.png=.png.o) $(addsuffix .o,$(BINFILES)) + +#--------------------------------------------------------------------------------- +# build a list of include paths +#--------------------------------------------------------------------------------- +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) -I$(PORTLIBS)/include + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(LIBOGC_LIB) -L$(PORTLIBS)/lib + +export OUTPUT := $(CURDIR)/$(TARGET) +.PHONY: $(BUILD) clean install + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin $(BUILD_DBG).elf + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).elf: $(OFILES) + +#--------------------------------------------------------------------------------- +# This rule links in binary data with the .jpg extension +#--------------------------------------------------------------------------------- +%.elf: link.ld $(OFILES) + @echo "linking ... $(TARGET).elf" + $(Q)$(LD) -n -T $^ $(LDFLAGS) -o ../$(BUILD_DBG).elf $(LIBPATHS) $(LIBS) + $(Q)$(OBJCOPY) -S -R .comment -R .gnu.attributes ../$(BUILD_DBG).elf $@ + $(Q)$(OBJCOPY) -O binary -R .comment -R .gnu.attributes ../$(BUILD_DBG).elf $@.bin + +#--------------------------------------------------------------------------------- +%.a: +#--------------------------------------------------------------------------------- + @echo $(notdir $@) + @rm -f $@ + @$(AR) -rc $@ $^ + +#--------------------------------------------------------------------------------- +%.o: %.cpp + @echo $(notdir $<) + @$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER) + +#--------------------------------------------------------------------------------- +%.o: %.c + @echo $(notdir $<) + @$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@ $(ERROR_FILTER) + +#--------------------------------------------------------------------------------- +%.o: %.S + @echo $(notdir $<) + @$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER) + +#--------------------------------------------------------------------------------- +%.png.o : %.png + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.jpg.o : %.jpg + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.ttf.o : %.ttf + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.bin.o : %.bin + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.wav.o : %.wav + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.mp3.o : %.mp3 + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.ogg.o : %.ogg + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) +#--------------------------------------------------------------------------------- +%.tga.o : %.tga + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/README.md b/README.md new file mode 100644 index 0000000..a7f7841 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# PayloadLoaderPayload +This payload.elf loader which can be used with any `payload.elf` loader. (For example [PayloadFromRPX](https://github.com/wiiu-env/PayloadFromRPX) or [JsTypeHax](https://github.com/wiiu-env/JsTypeHax)) + +## Usage +Place the `payload.elf` in the `sd:/wiiu` folder of your sd card and run a exploit which loads `payload.elf`. +Per default this will chainload `sd:/wiiu/payloads/default/payload.elf`, but when holding B while loading this payload, the target payload can be selected. + +Place payloads into seperate folder in `sd:/wiiu/payloads/` example: + +``` +sd:/wiiu/payloads/default/payload.elf +sd:/wiiu/payloads/legacy_env/payload.elf +sd:/wiiu/payloads/fw_img_loader/payload.elf +``` + +## 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 payloadloaderpayload-builder + +# make +docker run -it --rm -v ${PWD}:/project payloadloaderpayload-builder make + +# make clean +docker run -it --rm -v ${PWD}:/project payloadloaderpayload-builder make clean +``` + +## Credits +- Maschell +- orboditilt +- Copy pasted the solution for using wut header in .elf files from [RetroArch](https://github.com/libretro/RetroArch) \ No newline at end of file diff --git a/src/dynamic.c b/src/dynamic.c new file mode 100644 index 0000000..901352e --- /dev/null +++ b/src/dynamic.c @@ -0,0 +1,44 @@ +#include +#include + +#define IMPORT(name) void* addr_##name +#define IMPORT_BEGIN(lib) +#define IMPORT_END() + +#include "imports.h" + +#undef IMPORT +#undef IMPORT_BEGIN +#undef IMPORT_END + +#define IMPORT(name) do{if(OSDynLoad_FindExport(handle, 0, #name, &addr_##name) < 0)OSFatal("Function " # name " is NULL");} while(0) +#define IMPORT_BEGIN(lib) OSDynLoad_Acquire(#lib ".rpl", &handle) +/* #define IMPORT_END() OSDynLoad_Release(handle) */ +#define IMPORT_END() + +#define EXPORT_VAR(type, var) type var __attribute__((section(".data"))); + +EXPORT_VAR(uint32_t *, MEMAllocFromDefaultHeap); +EXPORT_VAR(uint32_t *, MEMAllocFromDefaultHeapEx); +EXPORT_VAR(uint32_t *, MEMFreeToDefaultHeap); + +void InitFunctionPointers(void) { + OSDynLoad_Module handle; + addr_OSDynLoad_Acquire = (void *) 0x0102A3B4; + addr_OSDynLoad_FindExport = (void *) 0x0102B828; + + OSDynLoad_Acquire("coreinit.rpl", &handle); + + uint32_t **value = 0; + OSDynLoad_FindExport(handle, 1, "MEMAllocFromDefaultHeap", (void **) &value); + MEMAllocFromDefaultHeap = *value; + OSDynLoad_FindExport(handle, 1, "MEMAllocFromDefaultHeapEx", (void **) &value); + MEMAllocFromDefaultHeapEx = *value; + OSDynLoad_FindExport(handle, 1, "MEMFreeToDefaultHeap", (void **) &value); + MEMFreeToDefaultHeap = *value; + +#include "imports.h" + + // override failed __rplwrap_exit find export + OSDynLoad_FindExport(handle, 0, "exit", (void **) &addr___rplwrap_exit); +} diff --git a/src/dynamic.h b/src/dynamic.h new file mode 100644 index 0000000..be625d1 --- /dev/null +++ b/src/dynamic.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void InitFunctionPointers(void); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/import_stub.S b/src/import_stub.S new file mode 100644 index 0000000..7bf8dc7 --- /dev/null +++ b/src/import_stub.S @@ -0,0 +1,24 @@ +/*#define IMPORT(name) \ + .global name; \ + name: \ + lis %r11, addr_##name@h; \ + lwz %r11, addr_##name@l(%r11); \ + mtctr %r11; \ + bctr*/ + +#define IMPORT(name) \ + .global name; \ + name: \ + lis %r11, addr_##name@h; \ + ori %r11, %r11, addr_##name@l; \ + lwz %r11, 0(%r11); \ + mtctr %r11; \ + bctr + +#define IMPORT_BEGIN(lib) +#define IMPORT_END() + +.align 2; +.section ".text"; + +#include "imports.h" \ No newline at end of file diff --git a/src/imports.h b/src/imports.h new file mode 100644 index 0000000..d5273d9 --- /dev/null +++ b/src/imports.h @@ -0,0 +1,295 @@ +/* coreinit */ +IMPORT_BEGIN(coreinit); + +IMPORT(OSScreenInit); +IMPORT(OSScreenGetBufferSizeEx); +IMPORT(OSScreenSetBufferEx); +IMPORT(OSScreenEnableEx); +IMPORT(OSScreenFlipBuffersEx); +IMPORT(OSScreenClearBufferEx); +IMPORT(OSScreenPutFontEx); +IMPORT(OSFatal); +IMPORT(OSDynLoad_Acquire); +IMPORT(OSDynLoad_FindExport); +IMPORT(OSDynLoad_Release); +IMPORT(OSSetExceptionCallback); +IMPORT(OSSavesDone_ReadyToRelease); +IMPORT(OSInitMutex); +IMPORT(OSLockMutex); +IMPORT(OSUnlockMutex); +IMPORT(OSInitCond); +IMPORT(OSWaitCond); +IMPORT(OSSignalCond); +IMPORT(OSInitSpinLock); +IMPORT(OSUninterruptibleSpinLock_Acquire); +IMPORT(OSUninterruptibleSpinLock_Release); +IMPORT(OSFastMutex_Init); +IMPORT(OSFastMutex_Lock); +IMPORT(OSFastMutex_Unlock); +IMPORT(OSSleepTicks); +IMPORT(OSGetTitleID); +IMPORT(OSIsThreadTerminated); +IMPORT(OSSetThreadPriority); +IMPORT(OSCreateThread); +IMPORT(OSSetThreadCleanupCallback); +IMPORT(OSResumeThread); +IMPORT(OSIsThreadSuspended); +IMPORT(OSSuspendThread); +IMPORT(OSGetCurrentThread); +IMPORT(OSExitThread); +IMPORT(OSJoinThread); +IMPORT(OSYieldThread); +IMPORT(OSGetCoreId); +IMPORT(OSIsMainCore); +IMPORT(OSGetSystemTime); +IMPORT(OSGetSystemTick); +IMPORT(OSGetTime); +IMPORT(OSGetSymbolName); +IMPORT(OSGetSharedData); +IMPORT(OSEffectiveToPhysical); +IMPORT(OSInitSemaphore); +IMPORT(OSInitSemaphoreEx); +IMPORT(OSGetSemaphoreCount); +IMPORT(OSSignalSemaphore); +IMPORT(OSWaitSemaphore); +IMPORT(OSTryWaitSemaphore); +IMPORT(OSCompareAndSwapAtomicEx); +IMPORT(OSCompareAndSwapAtomic); +IMPORT(OSGetThreadSpecific); +IMPORT(OSSetThreadSpecific); + +IMPORT(exit); +IMPORT(_Exit); +IMPORT(__os_snprintf); +IMPORT(DisassemblePPCRange); + +IMPORT(ICInvalidateRange); +IMPORT(DCInvalidateRange); +IMPORT(DCFlushRange); +IMPORT(DCStoreRange); +IMPORT(DCStoreRangeNoSync); + +IMPORT(__gh_errno_ptr); + +IMPORT(MEMGetBaseHeapHandle); +IMPORT(MEMCreateExpHeapEx); +IMPORT(MEMDestroyExpHeap); +IMPORT(MEMAllocFromExpHeapEx); +IMPORT(MEMFreeToExpHeap); +IMPORT(MEMGetSizeForMBlockExpHeap); +IMPORT(MEMAllocFromFrmHeapEx); +IMPORT(MEMFreeToFrmHeap); +IMPORT(MEMGetAllocatableSizeForFrmHeapEx); + +IMPORT(FSInit); +IMPORT(FSShutdown); +IMPORT(FSAddClient); +IMPORT(FSAddClientEx); +IMPORT(FSDelClient); +IMPORT(FSInitCmdBlock); +IMPORT(FSChangeDir); +IMPORT(FSGetFreeSpaceSize); +IMPORT(FSGetStat); +IMPORT(FSRemove); +IMPORT(FSOpenFile); +IMPORT(FSCloseFile); +IMPORT(FSOpenDir); +IMPORT(FSMakeDir); +IMPORT(FSReadDir); +IMPORT(FSRewindDir); +IMPORT(FSCloseDir); +IMPORT(FSGetStatFile); +IMPORT(FSReadFile); +IMPORT(FSWriteFile); +IMPORT(FSSetPosFile); +IMPORT(FSFlushFile); +IMPORT(FSTruncateFile); +IMPORT(FSRename); +IMPORT(FSGetMountSource); +IMPORT(FSMount); +IMPORT(FSUnmount); +IMPORT(FSChangeMode); +IMPORT(FSGetPosFile); +IMPORT(OSTicksToCalendarTime); +IMPORT(__rplwrap_exit); + +IMPORT(IOS_Open); +IMPORT(IOS_Close); +IMPORT(IOS_Ioctl); +IMPORT(IOS_IoctlAsync); + +IMPORT(IMIsAPDEnabled); +IMPORT(IMIsDimEnabled); +IMPORT(IMEnableAPD); +IMPORT(IMEnableDim); +IMPORT(IMDisableAPD); +IMPORT(IMDisableDim); + +IMPORT(OSGetSystemInfo); + +IMPORT_END(); + +/* nsysnet */ +IMPORT_BEGIN(nsysnet); + +IMPORT(socket_lib_init); +IMPORT(getaddrinfo); +IMPORT(freeaddrinfo); +IMPORT(getnameinfo); +IMPORT(inet_ntoa); +IMPORT(inet_ntop); +IMPORT(inet_aton); +IMPORT(inet_pton); +IMPORT(ntohl); +IMPORT(ntohs); +IMPORT(htonl); +IMPORT(htons); +IMPORT(accept); +IMPORT(bind); +IMPORT(socketclose); +IMPORT(connect); +IMPORT(getpeername); +IMPORT(getsockname); +IMPORT(getsockopt); +IMPORT(listen); +IMPORT(recv); +IMPORT(recvfrom); +IMPORT(send); +IMPORT(sendto); +IMPORT(setsockopt); +IMPORT(shutdown); +IMPORT(socket); +IMPORT(select); +IMPORT(socketlasterr); +IMPORT(socket_lib_finish); + +IMPORT_END(); + +/* gx2 */ +IMPORT_BEGIN(gx2); + +IMPORT(GX2Invalidate); +IMPORT(GX2Init); +IMPORT(GX2GetSystemTVScanMode); +IMPORT(GX2CalcTVSize); +IMPORT(GX2SetTVBuffer); +IMPORT(GX2CalcDRCSize); +IMPORT(GX2SetDRCBuffer); +IMPORT(GX2CalcSurfaceSizeAndAlignment); +IMPORT(GX2InitColorBufferRegs); +IMPORT(GX2SetupContextStateEx); +IMPORT(GX2SetContextState); +IMPORT(GX2SetColorBuffer); +IMPORT(GX2SetViewport); +IMPORT(GX2SetScissor); +IMPORT(GX2SetDepthOnlyControl); +IMPORT(GX2SetColorControl); +IMPORT(GX2SetBlendControl); +IMPORT(GX2SetBlendConstantColor); +IMPORT(GX2SetCullOnlyControl); +IMPORT(GX2CalcFetchShaderSizeEx); +IMPORT(GX2InitFetchShaderEx); +IMPORT(GX2SetFetchShader); +IMPORT(GX2SetVertexShader); +IMPORT(GX2SetPixelShader); +IMPORT(GX2SetGeometryShader); +IMPORT(GX2SetGeometryUniformBlock); +IMPORT(GX2SetVertexUniformBlock); +IMPORT(GX2SetPixelUniformBlock); +IMPORT(GX2CalcGeometryShaderInputRingBufferSize); +IMPORT(GX2CalcGeometryShaderOutputRingBufferSize); +IMPORT(GX2SetGeometryShaderInputRingBuffer); +IMPORT(GX2SetGeometryShaderOutputRingBuffer); +IMPORT(GX2SetShaderModeEx); +IMPORT(GX2SetAttribBuffer); +IMPORT(GX2InitTextureRegs); +IMPORT(GX2InitSampler); +IMPORT(GX2SetPixelTexture); +IMPORT(GX2SetPixelSampler); +IMPORT(GX2ClearColor); +IMPORT(GX2CopyColorBufferToScanBuffer); +IMPORT(GX2SwapScanBuffers); +IMPORT(GX2Flush); +IMPORT(GX2WaitForVsync); +IMPORT(GX2SetTVEnable); +IMPORT(GX2SetDRCEnable); +IMPORT(GX2SetSwapInterval); +IMPORT(GX2DrawDone); +IMPORT(GX2Shutdown); +IMPORT(GX2DrawEx); +IMPORT(GX2WaitForFlip); +IMPORT(GX2GetSwapStatus); + +IMPORT_END(); + +/* nn_ac */ +IMPORT_BEGIN(nn_ac); +IMPORT(ACInitialize); +IMPORT(ACFinalize); +IMPORT(ACConnect); +IMPORT(ACClose); +IMPORT(ACGetAssignedAddress); +IMPORT(ACGetAssignedSubnet); +IMPORT(Initialize__Q2_2nn3actFv); +IMPORT(GetSlotNo__Q2_2nn3actFv); +IMPORT(GetDefaultAccount__Q2_2nn3actFv); +IMPORT(Finalize__Q2_2nn3actFv); +IMPORT_END(); + +/* proc_ui */ +IMPORT_BEGIN(proc_ui); + +IMPORT(ProcUIInit); +IMPORT(ProcUIShutdown); +IMPORT(ProcUIDrawDoneRelease); +IMPORT(ProcUIProcessMessages); + +IMPORT_END(); + +/* sndcore2 */ +IMPORT_BEGIN(sndcore2); + +IMPORT(AXInitWithParams); +IMPORT(AXQuit); +IMPORT(AXRegisterFrameCallback); +IMPORT(AXAcquireMultiVoice); +IMPORT(AXSetMultiVoiceDeviceMix); +IMPORT(AXSetMultiVoiceOffsets); +IMPORT(AXSetMultiVoiceCurrentOffset); +IMPORT(AXSetMultiVoiceState); +IMPORT(AXSetMultiVoiceVe); +IMPORT(AXSetMultiVoiceSrcType); +IMPORT(AXSetMultiVoiceSrcRatio); +IMPORT(AXIsMultiVoiceRunning); +IMPORT(AXFreeMultiVoice); + +IMPORT_END(); + +/* sysapp */ +IMPORT_BEGIN(sysapp); + +IMPORT(SYSRelaunchTitle); +IMPORT(_SYSGetSystemApplicationTitleId); +IMPORT(SYSLaunchMenu); +IMPORT(_SYSLaunchMenuWithCheckingAccount); + +IMPORT_END(); + +/* vpad */ +IMPORT_BEGIN(vpad); + +IMPORT(VPADRead); +IMPORT(VPADInit); +IMPORT(VPADGetTPCalibratedPoint); + +IMPORT_END(); + + +/* nsyskbd */ +IMPORT_BEGIN(zlib125); + +IMPORT(inflateInit_); +IMPORT(inflate); +IMPORT(inflateEnd); + +IMPORT_END(); diff --git a/src/kernel.cpp b/src/kernel.cpp new file mode 100644 index 0000000..b417d4e --- /dev/null +++ b/src/kernel.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** + * Copyright (C) 2018-2020 Maschell + * + * 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 . + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "kernel.h" + +/* assembly functions */ +extern "C" void Syscall_0x36(void); +extern "C" void KernelPatchesRevertHook(void); +extern "C" void KernelPatches(void); + +void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value); + +extern "C" void SC_0x25_KernelCopyData(unsigned int addr, unsigned int src, unsigned int len); + +extern "C" void SCKernelCopyData(unsigned int addr, unsigned int src, unsigned int len); + +void KernelWriteU32(uint32_t addr, uint32_t value) { + ICInvalidateRange(&value, 4); + DCFlushRange(&value, 4); + + auto dst = (uint32_t) OSEffectiveToPhysical(addr); + auto src = (uint32_t) OSEffectiveToPhysical((uint32_t) &value); + + SC_0x25_KernelCopyData(dst, src, 4); + + DCFlushRange((void *) addr, 4); + ICInvalidateRange((void *) addr, 4); +} + +void revertMainHook() { + KernelWriteU32(0x0101c56c, 0x4E800421); +} + +void doKernelSetup() { + kern_write((void *) (KERN_SYSCALL_TBL_1 + (0x36 * 4)), (unsigned int) KernelPatches); + kern_write((void *) (KERN_SYSCALL_TBL_2 + (0x36 * 4)), (unsigned int) KernelPatches); + kern_write((void *) (KERN_SYSCALL_TBL_3 + (0x36 * 4)), (unsigned int) KernelPatches); + kern_write((void *) (KERN_SYSCALL_TBL_4 + (0x36 * 4)), (unsigned int) KernelPatches); + kern_write((void *) (KERN_SYSCALL_TBL_5 + (0x36 * 4)), (unsigned int) KernelPatches); + + Syscall_0x36(); +} + +void revertKernelHook() { + kern_write((void *) (KERN_SYSCALL_TBL_1 + (0x36 * 4)), (unsigned int) KernelPatchesRevertHook); + kern_write((void *) (KERN_SYSCALL_TBL_2 + (0x36 * 4)), (unsigned int) KernelPatchesRevertHook); + kern_write((void *) (KERN_SYSCALL_TBL_3 + (0x36 * 4)), (unsigned int) KernelPatchesRevertHook); + kern_write((void *) (KERN_SYSCALL_TBL_4 + (0x36 * 4)), (unsigned int) KernelPatchesRevertHook); + kern_write((void *) (KERN_SYSCALL_TBL_5 + (0x36 * 4)), (unsigned int) KernelPatchesRevertHook); + + Syscall_0x36(); +} + +/* Write a 32-bit word with kernel permissions */ +void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value) { + asm volatile ( + "li 3,1\n" + "li 4,0\n" + "mr 5,%1\n" + "li 6,0\n" + "li 7,0\n" + "lis 8,1\n" + "mr 9,%0\n" + "mr %1,1\n" + "li 0,0x3500\n" + "sc\n" + "nop\n" + "mr 1,%1\n" + : + : "r"(addr), "r"(value) + : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12" + ); +} diff --git a/src/kernel.h b/src/kernel.h new file mode 100644 index 0000000..319a98d --- /dev/null +++ b/src/kernel.h @@ -0,0 +1,38 @@ +/**************************************************************************** + * Copyright (C) 2018-2020 Maschell + * + * 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 . + ****************************************************************************/ + +#pragma once + +#define KERN_SYSCALL_TBL_1 0xFFE84C70 // unknown +#define KERN_SYSCALL_TBL_2 0xFFE85070 // works with games +#define KERN_SYSCALL_TBL_3 0xFFE85470 // works with loader +#define KERN_SYSCALL_TBL_4 0xFFEAAA60 // works with home menu +#define KERN_SYSCALL_TBL_5 0xFFEAAE60 // works with browser (previously KERN_SYSCALL_TBL) + +#ifdef __cplusplus +extern "C" { +#endif + +void doKernelSetup(); + +void doKernelSetup2(); + +void revertKernelHook(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/kernel_asm.S b/src/kernel_asm.S new file mode 100644 index 0000000..bbad787 --- /dev/null +++ b/src/kernel_asm.S @@ -0,0 +1,210 @@ +.section ".kernel_code" + .globl SaveAndResetDataBATs_And_SRs_hook +SaveAndResetDataBATs_And_SRs_hook: + # setup CTR to the position we need to return to + mflr r5 + mtctr r5 + # set link register to its original value + mtlr r7 + # setup us a nice DBAT for our code data with same region as our code + mfspr r5, 560 + mtspr 570, r5 + mfspr r5, 561 + mtspr 571, r5 + # restore the original kernel instructions that we replaced + lwz r5, 0x34(r3) + lwz r6, 0x38(r3) + lwz r7, 0x3C(r3) + lwz r8, 0x40(r3) + lwz r9, 0x44(r3) + lwz r10, 0x48(r3) + lwz r11, 0x4C(r3) + lwz r3, 0x50(r3) + isync + mtsr 7, r5 + # jump back to the position in kernel after our patch (from LR) + bctr + + +#define BAT_SETUP_HOOK_ADDR 0xFFF1D624 +# not all of those NOP address are required for every firmware +# mainly these should stop the kernel from removing our IBAT4 and DBAT5 +#define BAT_SET_NOP_ADDR_1 0xFFF06B6C +#define BAT_SET_NOP_ADDR_2 0xFFF06BF8 +#define BAT_SET_NOP_ADDR_3 0xFFF003C8 +#define BAT_SET_NOP_ADDR_4 0xFFF003CC +#define BAT_SET_NOP_ADDR_5 0xFFF1D70C +#define BAT_SET_NOP_ADDR_6 0xFFF1D728 +#define BAT_SET_NOP_ADDR_7 0xFFF1D82C + +#define BAT_SET_NOP_ADDR_8 0xFFEE11C4 +#define BAT_SET_NOP_ADDR_9 0xFFEE11C8 + +#define BAT_SETUP_HOOK_ENTRY 0x00FD0000 + + +#define BAT4U_VAL 0x008000FF +#define BAT4L_VAL 0x30800012 + + +#define SET_R4_TO_ADDR(addr) \ + lis r3, addr@h ; \ + ori r3, r3, addr@l ; \ + stw r4, 0(r3) ; \ + dcbf 0, r3 ; \ + icbi 0, r3 ; + + .globl Syscall_0x36 +Syscall_0x36: + li r0, 0x3600 + sc + blr + + .globl KernelPatches +KernelPatches: + # store the old DBAT0 + mfdbatu r5, 0 + mfdbatl r6, 0 + + # memory barrier + eieio + isync + + # setup DBAT0 for access to kernel code memory + lis r3, 0xFFF0 + ori r3, r3, 0x0002 + mtdbatu 0, r3 + lis r3, 0xFFF0 + ori r3, r3, 0x0032 + mtdbatl 0, r3 + + # memory barrier + eieio + isync + + # SaveAndResetDataBATs_And_SRs hook setup, but could be any BAT function though + # just chosen because its simple + lis r3, BAT_SETUP_HOOK_ADDR@h + ori r3, r3, BAT_SETUP_HOOK_ADDR@l + + # make the kernel setup our section in IBAT4 and + # jump to our function to restore the replaced instructions + lis r4, 0x3ce0 # lis r7, BAT4L_VAL@h + ori r4, r4, BAT4L_VAL@h + stw r4, 0x00(r3) + lis r4, 0x60e7 # ori r7, r7, BAT4L_VAL@l + ori r4, r4, BAT4L_VAL@l + stw r4, 0x04(r3) + lis r4, 0x7cf1 # mtspr 561, r7 + ori r4, r4, 0x8ba6 + stw r4, 0x08(r3) + lis r4, 0x3ce0 # lis r7, BAT4U_VAL@h + ori r4, r4, BAT4U_VAL@h + stw r4, 0x0C(r3) + lis r4, 0x60e7 # ori r7, r7, BAT4U_VAL@l + ori r4, r4, BAT4U_VAL@l + stw r4, 0x10(r3) + lis r4, 0x7cf0 # mtspr 560, r7 + ori r4, r4, 0x8ba6 + stw r4, 0x14(r3) + lis r4, 0x7c00 # eieio + ori r4, r4, 0x06ac + stw r4, 0x18(r3) + lis r4, 0x4c00 # isync + ori r4, r4, 0x012c + stw r4, 0x1C(r3) + lis r4, 0x7ce8 # mflr r7 + ori r4, r4, 0x02a6 + stw r4, 0x20(r3) + lis r4, (BAT_SETUP_HOOK_ENTRY | 0x48000003)@h # bla BAT_SETUP_HOOK_ENTRY + ori r4, r4, (BAT_SETUP_HOOK_ENTRY | 0x48000003)@l + stw r4, 0x24(r3) + + # flush and invalidate the replaced instructions + lis r3, (BAT_SETUP_HOOK_ADDR & ~31)@h + ori r3, r3, (BAT_SETUP_HOOK_ADDR & ~31)@l + dcbf 0, r3 + icbi 0, r3 + lis r3, ((BAT_SETUP_HOOK_ADDR + 0x20) & ~31)@h + ori r3, r3, ((BAT_SETUP_HOOK_ADDR + 0x20) & ~31)@l + dcbf 0, r3 + icbi 0, r3 + sync + + # setup IBAT4 for core 1 at this position (not really required but wont hurt) + # IBATL 4 + lis r3, BAT4L_VAL@h + ori r3, r3, BAT4L_VAL@l + mtspr 561, r3 + + # IBATU 4 + lis r3, BAT4U_VAL@h + ori r3, r3, BAT4U_VAL@l + mtspr 560, r3 + + # memory barrier + eieio + isync + + # write "nop" to some positions + lis r4, 0x6000 + # nop on IBATU 4 and DBAT 5 set/reset +#ifdef BAT_SET_NOP_ADDR_1 + SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_1) +#endif +#ifdef BAT_SET_NOP_ADDR_2 + SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_2) +#endif +#ifdef BAT_SET_NOP_ADDR_3 + SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_3) +#endif +#ifdef BAT_SET_NOP_ADDR_4 + SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_4) +#endif +#ifdef BAT_SET_NOP_ADDR_5 + SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_5) +#endif +#ifdef BAT_SET_NOP_ADDR_6 + SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_6) +#endif +#ifdef BAT_SET_NOP_ADDR_7 + SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_7) +#endif + +#if (defined(BAT_SET_NOP_ADDR_8) && defined(BAT_SET_NOP_ADDR_9)) + # memory barrier + eieio + isync + + # setup DBAT0 for access to kernel code memory + lis r3, 0xFFEE + ori r3, r3, 0x0002 + mtdbatu 0, r3 + lis r3, 0xFFEE + ori r3, r3, 0x0032 + mtdbatl 0, r3 + + # memory barrier + eieio + isync + + # write "nop" to some positions + lis r4, 0x6000 + SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_8) + SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_9) +#endif + + # memory barrier + eieio + isync + + # restore DBAT 0 and return from interrupt + mtdbatu 0, r5 + mtdbatl 0, r6 + + # memory barrier + eieio + isync + + blr + diff --git a/src/kernel_asm_revert.S b/src/kernel_asm_revert.S new file mode 100644 index 0000000..1c879f7 --- /dev/null +++ b/src/kernel_asm_revert.S @@ -0,0 +1,84 @@ +#define BAT_SETUP_HOOK_ADDR 0xFFF1D624 + + .globl KernelPatchesRevertHook +KernelPatchesRevertHook: + # store the old DBAT0 + mfdbatu r5, 0 + mfdbatl r6, 0 + + # memory barrier + eieio + isync + + # setup DBAT0 for access to kernel code memory + lis r3, 0xFFF0 + ori r3, r3, 0x0002 + mtdbatu 0, r3 + lis r3, 0xFFF0 + ori r3, r3, 0x0032 + mtdbatl 0, r3 + + # memory barrier + eieio + isync + + # restore kernel hook + lis r3, BAT_SETUP_HOOK_ADDR@h + ori r3, r3, BAT_SETUP_HOOK_ADDR@l + + lis r4, 0x80a3 # lwz r5 ,0x34 (r3 ) + ori r4, r4, 0x0034 + stw r4, 0x00(r3) + lis r4, 0x80c3 # lwz r6 ,0x38 (r3 ) + ori r4, r4, 0x0038 + stw r4, 0x04(r3) + lis r4, 0x80e3 # lwz r7 ,0x3c (r3 ) + ori r4, r4, 0x003c + stw r4, 0x08(r3) + lis r4, 0x8103 # lwz r8 ,0x40 (r3 ) + ori r4, r4, 0x0040 + stw r4, 0x0C(r3) + lis r4, 0x8123 # lwz r9 ,0x44 (r3 ) + ori r4, r4, 0x0044 + stw r4, 0x10(r3) + lis r4, 0x8143 # lwz r10 ,0x48 (r3 ) + ori r4, r4, 0x0048 + stw r4, 0x14(r3) + lis r4, 0x8163 # lwz r11 ,0x4c (r3 ) + ori r4, r4, 0x004c + stw r4, 0x18(r3) + lis r4, 0x8063 # lwz r3 ,0x50 (r3 ) + ori r4, r4, 0x0050 + stw r4, 0x1C(r3) + lis r4, 0x4c00 # isync + ori r4, r4, 0x012c + stw r4, 0x20(r3) + lis r4, 0x7ca7 # mtsr sr7 ,r5 + ori r4, r4, 0x01a4 + stw r4, 0x24(r3) + + # flush and invalidate the replaced instructions + lis r3, (BAT_SETUP_HOOK_ADDR & ~31)@h + ori r3, r3, (BAT_SETUP_HOOK_ADDR & ~31)@l + dcbf 0, r3 + icbi 0, r3 + lis r3, ((BAT_SETUP_HOOK_ADDR + 0x20) & ~31)@h + ori r3, r3, ((BAT_SETUP_HOOK_ADDR + 0x20) & ~31)@l + dcbf 0, r3 + icbi 0, r3 + sync + + # memory barrier + eieio + isync + + # restore DBAT 0 and return from interrupt + mtdbatu 0, r5 + mtdbatl 0, r6 + + # memory barrier + eieio + isync + + blr + diff --git a/src/kernel_copy.S b/src/kernel_copy.S new file mode 100644 index 0000000..434a7c0 --- /dev/null +++ b/src/kernel_copy.S @@ -0,0 +1,27 @@ +.global SCKernelCopyData +SCKernelCopyData: + // Disable data address translation + mfmsr %r6 + li %r7, 0x10 + andc %r6, %r6, %r7 + mtmsr %r6 + + // Copy data + addi %r3, %r3, -1 + addi %r4, %r4, -1 + mtctr %r5 +SCKernelCopyData_loop: + lbzu %r5, 1(%r4) + stbu %r5, 1(%r3) + bdnz SCKernelCopyData_loop + + // Enable data address translation + ori %r6, %r6, 0x10 + mtmsr %r6 +blr + +.global SC_0x25_KernelCopyData +SC_0x25_KernelCopyData: + li %r0, 0x2500 + sc +blr \ No newline at end of file diff --git a/src/link.ld b/src/link.ld new file mode 100644 index 0000000..ef75601 --- /dev/null +++ b/src/link.ld @@ -0,0 +1,26 @@ +OUTPUT(payload.elf); + +ENTRY(_start); + +SECTIONS { + . = 0x00FD0000; + .text : { + *(.kernel_code*); + *(.text*); + /* Tell linker to not garbage collect this section as it is not referenced anywhere */ + KEEP(*(.kernel_code*)); + } + .data : { + *(.rodata*); + *(.data*); + *(.sdata*); + *(.bss*); + *(.sbss*); + } + __CODE_END = .; + /DISCARD/ : { + *(*); + } +} + +ASSERT((SIZEOF(.text) + SIZEOF(.data)) < 0x30000, "elf is too big"); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..9c9acc3 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,241 @@ +/**************************************************************************** + * Copyright (C) 2018-2020 Maschell + * + * 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 . + ****************************************************************************/ + +#include +#include +#include + +#include "utils/ElfUtils.h" +#include "utils/logger.h" +#include "dynamic.h" +#include "kernel.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +std::map get_all_payloads(const char *relativefilepath); + +std::vector readDirFull(const char *base_path, const char *path, FSCmdBlock &cmd, FSClient &client, int filter); + +std::string PayloadSelectionScreen(const std::map &payloads); + +extern "C" void __init_wut(); +extern "C" void __fini_wut(); + +extern "C" uint32_t start_wrapper(int argc, char **argv) { + doKernelSetup(); + InitFunctionPointers(); + + __init_wut(); + + WHBLogUdpInit(); + + DEBUG_FUNCTION_LINE("Hello from payload"); + + VPADReadError err; + VPADStatus vpad_data; + VPADRead(VPAD_CHAN_0, &vpad_data, 1, &err); + + uint32_t btn = vpad_data.hold | vpad_data.trigger; + + std::map payloads = get_all_payloads("wiiu/payloads"); + + uint32_t entryPoint = 0; + + std::string payload_path = "wiiu/payloads/default/payload.elf"; + if ((btn & VPAD_BUTTON_B) == VPAD_BUTTON_B) { + payload_path = PayloadSelectionScreen(payloads); + DEBUG_FUNCTION_LINE("Selected %s", payload_path.c_str()); + } + + entryPoint = load_loader_elf_from_sd(nullptr, payload_path.c_str()); + + if (entryPoint != 0) { + DEBUG_FUNCTION_LINE("loaded payload entrypoint at %08X", entryPoint); + } else { + DEBUG_FUNCTION_LINE("failed to load elf"); + } + + WHBLogUdpDeinit(); + + __fini_wut(); + + revertKernelHook(); + + return entryPoint; +} +extern "C" int _start(int argc, char **argv) { + uint32_t entryPoint = start_wrapper(argc, argv); + int res = -1; + if (entryPoint != 0) { + res = ((int (*)(int, char **)) entryPoint)(argc, argv); + } + return res; +} + +std::map get_all_payloads(const char *relativefilepath) { + std::map result; + const char *sdRootPath = ""; + std::vector payload_folders; + std::vector files_inFolder; + bool clientAdded = false; + if (!WHBMountSdCard()) { + DEBUG_FUNCTION_LINE("Failed to mount SD Card..."); + goto exit; + } + + FSCmdBlock cmd; + FSClient client; + + sdRootPath = WHBGetSdCardMountPath(); + + FSAddClient(&client, -1); + clientAdded = true; + + FSInitCmdBlock(&cmd); + + payload_folders = readDirFull(sdRootPath, relativefilepath, cmd, client, 1); + + for (auto &e : payload_folders) { + DEBUG_FUNCTION_LINE("Reading path %s", e.c_str()); + files_inFolder = readDirFull(sdRootPath, e.c_str(), cmd, client, 2); + + for (auto &child : files_inFolder) { + if (StringTools::EndsWith(child, "payload.elf")) { + std::vector folders = StringTools::stringSplit(e, "/"); + std::string folder_name = e; + if (folders.size() > 1) { + folder_name = folders.at(folders.size() - 1); + } + + DEBUG_FUNCTION_LINE("%s is valid!", folder_name.c_str()); + result[folder_name] = child; + break; + } + } + } + + exit: + WHBUnmountSdCard(); + if (clientAdded) { + FSDelClient(&client, -1); + } + return result; +} + +std::vector readDirFull(const char *base_path, const char *path, FSCmdBlock &cmd, FSClient &client, int filter) { + std::string full_dir_path = StringTools::strfmt("%s/%s", base_path, path); + FSStatus status; + FSDirectoryHandle handle; + std::vector result; + if (FSOpenDir(&client, &cmd, full_dir_path.c_str(), &handle, -1) == FS_STATUS_OK) { + FSDirectoryEntry entry; + while (true) { + status = FSReadDir(&client, &cmd, handle, &entry, -1); + if (status < 0) { + break; + } + std::string filepath = StringTools::strfmt("%s/%s", path, entry.name); + + if (entry.info.flags & FS_STAT_DIRECTORY && filter <= 1) { + result.push_back(filepath); + } else if (filter == 0 || filter == 2) { + result.push_back(filepath); + } + } + } else { + DEBUG_FUNCTION_LINE("Failed to open dir %s", path); + } + return result; +} + + +std::string PayloadSelectionScreen(const std::map &payloads) { + int32_t screen_buf0_size = 0; + + // Init screen and screen buffers + OSScreenInit(); + screen_buf0_size = OSScreenGetBufferSizeEx(SCREEN_TV); + OSScreenSetBufferEx(SCREEN_TV, (void *) 0xF4000000); + OSScreenSetBufferEx(SCREEN_DRC, (void *) (0xF4000000 + screen_buf0_size)); + + OSScreenEnableEx(SCREEN_TV, 1); + OSScreenEnableEx(SCREEN_DRC, 1); + + // Clear screens + OSScreenClearBufferEx(SCREEN_TV, 0); + OSScreenClearBufferEx(SCREEN_DRC, 0); + + OSScreenFlipBuffersEx(SCREEN_TV); + OSScreenFlipBuffersEx(SCREEN_DRC); + + VPADStatus vpad_data; + VPADReadError error; + int selected = 0; + while (true) { + // Clear screens + OSScreenClearBufferEx(SCREEN_TV, 0); + OSScreenClearBufferEx(SCREEN_DRC, 0); + + int pos = 0; + int i = 0; + for (auto const&[key, val] : payloads) { + std::string text = StringTools::strfmt("%s %s", i == selected ? "> " : " ", key.c_str()); + OSScreenPutFontEx(SCREEN_TV, 0, pos, text.c_str()); + OSScreenPutFontEx(SCREEN_DRC, 0, pos, text.c_str()); + i++; + pos++; + } + + VPADRead(VPAD_CHAN_0, &vpad_data, 1, &error); + if (vpad_data.trigger == VPAD_BUTTON_A) { + break; + } + + if (vpad_data.trigger == VPAD_BUTTON_UP) { + selected--; + if (selected < 0) { + selected = 0; + } + } else if (vpad_data.trigger == VPAD_BUTTON_DOWN) { + selected++; + if ((uint32_t) selected >= payloads.size()) { + selected = payloads.size() - 1; + } + } + + OSScreenFlipBuffersEx(SCREEN_TV); + OSScreenFlipBuffersEx(SCREEN_DRC); + + OSSleepTicks(OSMillisecondsToTicks(16)); + } + int i = 0; + for (auto const&[key, val] : payloads) { + if (i == selected) { + return val; + } + i++; + } + return ""; +} \ No newline at end of file diff --git a/src/utils/ElfUtils.c b/src/utils/ElfUtils.c new file mode 100644 index 0000000..ed685ac --- /dev/null +++ b/src/utils/ElfUtils.c @@ -0,0 +1,149 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "elf_abi.h" + +int32_t LoadFileToMem(const char *relativefilepath, char **fileOut, uint32_t *sizeOut) { + char path[256]; + int result = 0; + const char *sdRootPath = ""; + if (!WHBMountSdCard()) { + DEBUG_FUNCTION_LINE("Failed to mount SD Card..."); + result = -1; + goto exit; + } + + sdRootPath = WHBGetSdCardMountPath(); + sprintf(path, "%s/%s", sdRootPath, relativefilepath); + + DEBUG_FUNCTION_LINE("Loading file %s.", path); + + *fileOut = WHBReadWholeFile(path, sizeOut); + if (!(*fileOut)) { + result = -2; + DEBUG_FUNCTION_LINE("WHBReadWholeFile(%s) returned NULL", path); + goto exit; + } + + exit: + WHBUnmountSdCard(); + WHBDeInitFileSystem(); + return result; +} + +static void InstallMain(void *data_elf); + +uint32_t load_loader_elf_from_sd(unsigned char *baseAddress, const char *relativePath) { + char *elf_data = NULL; + uint32_t fileSize = 0; + if (LoadFileToMem(relativePath, &elf_data, &fileSize) != 0) { + return 0; + } + + InstallMain(elf_data); + + Elf32_Ehdr *ehdr = (Elf32_Ehdr *) elf_data; + + uint32_t res = ehdr->e_entry; + + MEMFreeToDefaultHeap((void *) elf_data); + + return res; +} + +static unsigned int get_section(void *data, const char *name, unsigned int *size, unsigned int *addr, int fail_on_not_found) { + Elf32_Ehdr *ehdr = (Elf32_Ehdr *) data; + + if (!data + || !IS_ELF (*ehdr) + || (ehdr->e_type != ET_EXEC) + || (ehdr->e_machine != EM_PPC)) { + OSFatal("Invalid elf file"); + } + + Elf32_Shdr *shdr = (Elf32_Shdr *) ((uint32_t) data + ehdr->e_shoff); + int i; + for (i = 0; i < ehdr->e_shnum; i++) { + const char *section_name = ((const char *) data) + shdr[ehdr->e_shstrndx].sh_offset + shdr[i].sh_name; + if (strcmp(section_name, name) == 0) { + if (addr) { + *addr = shdr[i].sh_addr; + } + if (size) { + *size = shdr[i].sh_size; + } + return shdr[i].sh_offset; + } + } + + if (fail_on_not_found) { + OSFatal((char *) name); + } + + return 0; +} + +/* ****************************************************************** */ +/* INSTALL MAIN CODE */ +/* ****************************************************************** */ +static void InstallMain(void *data_elf) { + // get .text section + unsigned int main_text_addr = 0; + unsigned int main_text_len = 0; + unsigned int section_offset = get_section(data_elf, ".text", &main_text_len, &main_text_addr, 1); + unsigned char *main_text = (unsigned char *)((uint32_t) data_elf + section_offset); + /* Copy main .text to memory */ + if (section_offset > 0) { + DEBUG_FUNCTION_LINE("Copy section to %08X from %08X (size: %d)", main_text_addr, main_text, main_text_len); + memcpy((void *) (main_text_addr), (void *) main_text, main_text_len); + DCFlushRange((void *) main_text_addr, main_text_len); + ICInvalidateRange((void *) main_text_addr, main_text_len); + } + + + // get the .rodata section + unsigned int main_rodata_addr = 0; + unsigned int main_rodata_len = 0; + section_offset = get_section(data_elf, ".rodata", &main_rodata_len, &main_rodata_addr, 0); + if (section_offset > 0) { + unsigned char *main_rodata = (unsigned char *)((uint32_t) data_elf + section_offset); + /* Copy main rodata to memory */ + memcpy((void *) (main_rodata_addr), (void *) main_rodata, main_rodata_len); + DCFlushRange((void *) main_rodata_addr, main_rodata_len); + ICInvalidateRange((void *) main_rodata_addr, main_rodata_len); + + } + + // get the .data section + unsigned int main_data_addr = 0; + unsigned int main_data_len = 0; + section_offset = get_section(data_elf, ".data", &main_data_len, &main_data_addr, 0); + if (section_offset > 0) { + unsigned char *main_data = (unsigned char *)((uint32_t) data_elf + section_offset); + /* Copy main data to memory */ + memcpy((void *) (main_data_addr), (void *) main_data, main_data_len); + DCFlushRange((void *) main_data_addr, main_data_len); + ICInvalidateRange((void *) main_data_addr, main_data_len); + } + + // get the .bss section + unsigned int main_bss_addr = 0; + unsigned int main_bss_len = 0; + section_offset = get_section(data_elf, ".bss", &main_bss_len, &main_bss_addr, 0); + if (section_offset > 0) { + unsigned char *main_bss = (unsigned char *)((uint32_t) data_elf + section_offset); + /* Copy main data to memory */ + memcpy((void *) (main_bss_addr), (void *) main_bss, main_bss_len); + DCFlushRange((void *) main_bss_addr, main_bss_len); + ICInvalidateRange((void *) main_bss_addr, main_bss_len); + } + +} diff --git a/src/utils/ElfUtils.h b/src/utils/ElfUtils.h new file mode 100644 index 0000000..c13087b --- /dev/null +++ b/src/utils/ElfUtils.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +extern "C" int32_t LoadFileToMem(const char *relativefilepath, char **fileOut, uint32_t *sizeOut); +extern "C" uint32_t load_loader_elf_from_sd(unsigned char *baseAddress, const char *relativePath); + diff --git a/src/utils/StringTools.cpp b/src/utils/StringTools.cpp new file mode 100644 index 0000000..c60227e --- /dev/null +++ b/src/utils/StringTools.cpp @@ -0,0 +1,304 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +BOOL StringTools::EndsWith(const std::string &a, const std::string &b) { + if (b.size() > a.size()) { + return false; + } + return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin()); +} + +const char *StringTools::byte_to_binary(int32_t x) { + static char b[9]; + b[0] = '\0'; + + int32_t z; + for (z = 128; z > 0; z >>= 1) { + strcat(b, ((x & z) == z) ? "1" : "0"); + } + + return b; +} + +std::string StringTools::removeCharFromString(std::string &input, char toBeRemoved) { + std::string output = input; + size_t position; + while (1) { + position = output.find(toBeRemoved); + if (position == std::string::npos) { + break; + } + output.erase(position, 1); + } + return output; +} + +const char *StringTools::fmt(const char *format, ...) { + static char strChar[512]; + strChar[0] = 0; + + va_list va; + va_start(va, format); + if ((vsprintf(strChar, format, va) >= 0)) { + va_end(va); + return (const char *) strChar; + } + va_end(va); + + return NULL; +} + +const wchar_t *StringTools::wfmt(const char *format, ...) { + static char tmp[512]; + static wchar_t strWChar[512]; + strWChar[0] = 0; + tmp[0] = 0; + + if (!format) { + return (const wchar_t *) strWChar; + } + + if (strcmp(format, "") == 0) { + return (const wchar_t *) strWChar; + } + + va_list va; + va_start(va, format); + if ((vsprintf(tmp, format, va) >= 0)) { + int bt; + int32_t strlength = strlen(tmp); + bt = mbstowcs(strWChar, tmp, (strlength < 512) ? strlength : 512); + + if (bt > 0) { + strWChar[bt] = 0; + return (const wchar_t *) strWChar; + } + } + va_end(va); + + return NULL; +} + +int32_t StringTools::strprintf(std::string &str, const char *format, ...) { + static char tmp[512]; + tmp[0] = 0; + int32_t result = 0; + + va_list va; + va_start(va, format); + if ((vsprintf(tmp, format, va) >= 0)) { + str = tmp; + result = str.size(); + } + va_end(va); + + return result; +} + +std::string StringTools::strfmt(const char *format, ...) { + std::string str; + static char tmp[512]; + tmp[0] = 0; + + va_list va; + va_start(va, format); + if ((vsprintf(tmp, format, va) >= 0)) { + str = tmp; + } + va_end(va); + + return str; +} + +BOOL StringTools::char2wchar_t(const char *strChar, wchar_t *dest) { + if (!strChar || !dest) { + return false; + } + + int bt; + bt = mbstowcs(dest, strChar, strlen(strChar)); + if (bt > 0) { + dest[bt] = 0; + return true; + } + + return false; +} + +int32_t StringTools::strtokcmp(const char *string, const char *compare, const char *separator) { + if (!string || !compare) { + return -1; + } + + char TokCopy[512]; + strncpy(TokCopy, compare, sizeof(TokCopy)); + TokCopy[511] = '\0'; + + char *strTok = strtok(TokCopy, separator); + + while (strTok != NULL) { + if (strcasecmp(string, strTok) == 0) { + return 0; + } + strTok = strtok(NULL, separator); + } + + return -1; +} + +int32_t StringTools::strextcmp(const char *string, const char *extension, char seperator) { + if (!string || !extension) { + return -1; + } + + char *ptr = strrchr(string, seperator); + if (!ptr) { + return -1; + } + + return strcasecmp(ptr + 1, extension); +} + + +std::vector StringTools::stringSplit(const std::string &inValue, const std::string &splitter) { + std::string value = inValue; + std::vector result; + while (true) { + uint32_t index = value.find(splitter); + if (index == std::string::npos) { + result.push_back(value); + break; + } + std::string first = value.substr(0, index); + result.push_back(first); + if (index + splitter.size() == value.length()) { + result.push_back(""); + break; + } + if (index + splitter.size() > value.length()) { + break; + } + value = value.substr(index + splitter.size(), value.length()); + } + return result; +} + + +const char *StringTools::FullpathToFilename(const char *path) { + if (!path) { + return path; + } + + const char *ptr = path; + const char *Filename = ptr; + + while (*ptr != '\0') { + if (ptr[0] == '/' && ptr[1] != '\0') { + Filename = ptr + 1; + } + + ++ptr; + } + + return Filename; +} + +void StringTools::RemoveDoubleSlashs(std::string &str) { + uint32_t length = str.size(); + + //! clear path of double slashes + for (uint32_t i = 1; i < length; ++i) { + if (str[i - 1] == '/' && str[i] == '/') { + str.erase(i, 1); + i--; + length--; + } + } +} + + +// You must free the result if result is non-NULL. +char *StringTools::str_replace(char *orig, char *rep, char *with) { + char *result; // the return string + char *ins; // the next insert point + char *tmp; // varies + int len_rep; // length of rep (the string to remove) + int len_with; // length of with (the string to replace rep with) + int len_front; // distance between rep and end of last rep + int count; // number of replacements + + // sanity checks and initialization + if (!orig || !rep) { + return NULL; + } + len_rep = strlen(rep); + if (len_rep == 0) { + return NULL; + } // empty rep causes infinite loop during count + if (!with) { + with = (char *) ""; + } + len_with = strlen(with); + + // count the number of replacements needed + ins = orig; + for (count = 0; (tmp = strstr(ins, rep)); ++count) { + ins = tmp + len_rep; + } + + tmp = result = (char *) malloc(strlen(orig) + (len_with - len_rep) * count + 1); + + if (!result) { + return NULL; + } + + // first time through the loop, all the variable are set correctly + // from here on, + // tmp points to the end of the result string + // ins points to the next occurrence of rep in orig + // orig points to the remainder of orig after "end of rep" + while (count--) { + ins = strstr(orig, rep); + len_front = ins - orig; + tmp = strncpy(tmp, orig, len_front) + len_front; + tmp = strcpy(tmp, with) + len_with; + orig += len_front + len_rep; // move to next "end of rep" + } + strcpy(tmp, orig); + return result; +} diff --git a/src/utils/StringTools.h b/src/utils/StringTools.h new file mode 100644 index 0000000..6c53f0d --- /dev/null +++ b/src/utils/StringTools.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#pragma once + +#include +#include +#include + +class StringTools { +public: + static BOOL EndsWith(const std::string &a, const std::string &b); + + static const char *byte_to_binary(int32_t x); + + static std::string removeCharFromString(std::string &input, char toBeRemoved); + + static const char *fmt(const char *format, ...); + + static const wchar_t *wfmt(const char *format, ...); + + static int32_t strprintf(std::string &str, const char *format, ...); + + static std::string strfmt(const char *format, ...); + + static BOOL char2wchar_t(const char *src, wchar_t *dest); + + static int32_t strtokcmp(const char *string, const char *compare, const char *separator); + + static int32_t strextcmp(const char *string, const char *extension, char seperator); + + static char *str_replace(char *orig, char *rep, char *with); + + static const char *FullpathToFilename(const char *path); + + static void RemoveDoubleSlashs(std::string &str); + + static std::vector stringSplit(const std::string &value, const std::string &splitter); +}; diff --git a/src/utils/elf_abi.h b/src/utils/elf_abi.h new file mode 100644 index 0000000..4d9c796 --- /dev/null +++ b/src/utils/elf_abi.h @@ -0,0 +1,591 @@ +/* + * Copyright (c) 1995, 1996, 2001, 2002 + * Erik Theisen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This is the ELF ABI header file + * formerly known as "elf_abi.h". + */ + +#ifndef _ELF_ABI_H +#define _ELF_ABI_H + +/* + * This version doesn't work for 64-bit ABIs - Erik. + */ + +/* + * These typedefs need to be handled better. + */ +typedef unsigned int Elf32_Addr; /* Unsigned program address */ +typedef unsigned int Elf32_Off; /* Unsigned file offset */ +typedef signed int Elf32_Sword; /* Signed large integer */ +typedef unsigned int Elf32_Word; /* Unsigned large integer */ +typedef unsigned short Elf32_Half; /* Unsigned medium integer */ + +/* e_ident[] identification indexes */ +#define EI_MAG0 0 /* file ID */ +#define EI_MAG1 1 /* file ID */ +#define EI_MAG2 2 /* file ID */ +#define EI_MAG3 3 /* file ID */ +#define EI_CLASS 4 /* file class */ +#define EI_DATA 5 /* data encoding */ +#define EI_VERSION 6 /* ELF header version */ +#define EI_OSABI 7 /* OS/ABI specific ELF extensions */ +#define EI_ABIVERSION 8 /* ABI target version */ +#define EI_PAD 9 /* start of pad bytes */ +#define EI_NIDENT 16 /* Size of e_ident[] */ + +/* e_ident[] magic number */ +#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */ +#define ELFMAG1 'E' /* e_ident[EI_MAG1] */ +#define ELFMAG2 'L' /* e_ident[EI_MAG2] */ +#define ELFMAG3 'F' /* e_ident[EI_MAG3] */ +#define ELFMAG "\177ELF" /* magic */ +#define SELFMAG 4 /* size of magic */ + +/* e_ident[] file class */ +#define ELFCLASSNONE 0 /* invalid */ +#define ELFCLASsigned int 1 /* 32-bit objs */ +#define ELFCLASS64 2 /* 64-bit objs */ +#define ELFCLASSNUM 3 /* number of classes */ + +/* e_ident[] data encoding */ +#define ELFDATANONE 0 /* invalid */ +#define ELFDATA2LSB 1 /* Little-Endian */ +#define ELFDATA2MSB 2 /* Big-Endian */ +#define ELFDATANUM 3 /* number of data encode defines */ + +/* e_ident[] OS/ABI specific ELF extensions */ +#define ELFOSABI_NONE 0 /* No extension specified */ +#define ELFOSABI_HPUX 1 /* Hewlett-Packard HP-UX */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* Linux */ +#define ELFOSABI_SOLARIS 6 /* Sun Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +/* 64-255 Architecture-specific value range */ + +/* e_ident[] ABI Version */ +#define ELFABIVERSION 0 + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* ELF Header */ +typedef struct elfhdr{ + unsigned char e_ident[EI_NIDENT]; /* ELF Identification */ + Elf32_Half e_type; /* object file type */ + Elf32_Half e_machine; /* machine */ + Elf32_Word e_version; /* object file version */ + Elf32_Addr e_entry; /* virtual entry point */ + Elf32_Off e_phoff; /* program header table offset */ + Elf32_Off e_shoff; /* section header table offset */ + Elf32_Word e_flags; /* processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size */ + Elf32_Half e_phentsize; /* program header entry size */ + Elf32_Half e_phnum; /* number of program header entries */ + Elf32_Half e_shentsize; /* section header entry size */ + Elf32_Half e_shnum; /* number of section header entries */ + Elf32_Half e_shstrndx; /* section header table's "section + header string table" entry offset */ +} Elf32_Ehdr; + +/* e_type */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* relocatable file */ +#define ET_EXEC 2 /* executable file */ +#define ET_DYN 3 /* shared object file */ +#define ET_CORE 4 /* core file */ +#define ET_NUM 5 /* number of types */ +#define ET_LOOS 0xfe00 /* reserved range for operating */ +#define ET_HIOS 0xfeff /* system specific e_type */ +#define ET_LOPROC 0xff00 /* reserved range for processor */ +#define ET_HIPROC 0xffff /* specific e_type */ + +/* e_machine */ +#define EM_NONE 0 /* No Machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola 68000 */ +#define EM_88K 5 /* Motorola 88000 */ +#if 0 +#define EM_486 6 /* RESERVED - was Intel 80486 */ +#endif +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */ +#define EM_S370 9 /* IBM System/370 Processor */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#if 0 +#define EM_SPARC64 11 /* RESERVED - was SPARC v9 + 64-bit unoffical */ +#endif +/* RESERVED 11-14 for future use */ +#define EM_PARISC 15 /* HPPA */ +/* RESERVED 16 for future use */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* 64-bit PowerPC */ +#define EM_S390 22 /* IBM System/390 Processor */ +/* RESERVED 23-35 for future use */ +#define EM_V800 36 /* NEC V800 */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_RCE 39 /* Motorola RCE */ +#define EM_ARM 40 /* Advanced Risc Machines ARM */ +#define EM_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Hitachi SH */ +#define EM_SPARCV9 43 /* SPARC Version 9 */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor */ +#define EM_ARC 45 /* Argonaut RISC Core */ +#define EM_H8_300 46 /* Hitachi H8/300 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +#define EM_H8_500 49 /* Hitachi H8/500 */ +#define EM_IA_64 50 /* Intel Merced */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Start*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ +#define EM_X86_64 62 /* AMD x86-64 */ +#define EM_PDSP 63 /* Sony DSP Processor */ +/* RESERVED 64,65 for future use */ +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CHRIS 76 /* Axis Communications embedded proc. */ +#define EM_JAVELIN 77 /* Infineon Technologies emb. proc. */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's edu 64-bit proc. */ +#define EM_HUANY 81 /* Harvard University mach-indep objs */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi DV10V */ +#define EM_D30V 86 /* Mitsubishi DV30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Mitsubishi M32R */ +#define EM_MN10300 89 /* Matsushita MN10200 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_NUM 92 /* number of machine types */ + +/* Version */ +#define EV_NONE 0 /* Invalid */ +#define EV_CURRENT 1 /* Current */ +#define EV_NUM 2 /* number of versions */ + +/* Section Header */ +typedef struct { + Elf32_Word sh_name; /* name - index into section header + string table section */ + Elf32_Word sh_type; /* type */ + Elf32_Word sh_flags; /* flags */ + Elf32_Addr sh_addr; /* address */ + Elf32_Off sh_offset; /* file offset */ + Elf32_Word sh_size; /* section size */ + Elf32_Word sh_link; /* section header table index link */ + Elf32_Word sh_info; /* extra information */ + Elf32_Word sh_addralign; /* address alignment */ + Elf32_Word sh_entsize; /* section entry size */ +} Elf32_Shdr; + +/* Special Section Indexes */ +#define SHN_UNDEF 0 /* undefined */ +#define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */ +#define SHN_LOPROC 0xff00 /* reserved range for processor */ +#define SHN_HIPROC 0xff1f /* specific section indexes */ +#define SHN_LOOS 0xff20 /* reserved range for operating */ +#define SHN_HIOS 0xff3f /* specific semantics */ +#define SHN_ABS 0xfff1 /* absolute value */ +#define SHN_COMMON 0xfff2 /* common symbol */ +#define SHN_XINDEX 0xffff /* Index is an extra table */ +#define SHN_HIRESERVE 0xffff /* upper bounds of reserved indexes */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends*/ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relation section without addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* number of section types */ +#define SHT_LOOS 0x60000000 /* Start OS-specific */ +#define SHT_HIOS 0x6fffffff /* End OS-specific */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Section names */ +#define ELF_BSS ".bss" /* uninitialized data */ +#define ELF_COMMENT ".comment" /* version control information */ +#define ELF_DATA ".data" /* initialized data */ +#define ELF_DATA1 ".data1" /* initialized data */ +#define ELF_DEBUG ".debug" /* debug */ +#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */ +#define ELF_DYNSTR ".dynstr" /* dynamic string table */ +#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */ +#define ELF_FINI ".fini" /* termination code */ +#define ELF_FINI_ARRAY ".fini_array" /* Array of destructors */ +#define ELF_GOT ".got" /* global offset table */ +#define ELF_HASH ".hash" /* symbol hash table */ +#define ELF_INIT ".init" /* initialization code */ +#define ELF_INIT_ARRAY ".init_array" /* Array of constuctors */ +#define ELF_INTERP ".interp" /* Pathname of program interpreter */ +#define ELF_LINE ".line" /* Symbolic line numnber information */ +#define ELF_NOTE ".note" /* Contains note section */ +#define ELF_PLT ".plt" /* Procedure linkage table */ +#define ELF_PREINIT_ARRAY ".preinit_array" /* Array of pre-constructors */ +#define ELF_REL_DATA ".rel.data" /* relocation data */ +#define ELF_REL_FINI ".rel.fini" /* relocation termination code */ +#define ELF_REL_INIT ".rel.init" /* relocation initialization code */ +#define ELF_REL_DYN ".rel.dyn" /* relocaltion dynamic link info */ +#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */ +#define ELF_REL_TEXT ".rel.text" /* relocation code */ +#define ELF_RODATA ".rodata" /* read-only data */ +#define ELF_RODATA1 ".rodata1" /* read-only data */ +#define ELF_SHSTRTAB ".shstrtab" /* section header string table */ +#define ELF_STRTAB ".strtab" /* string table */ +#define ELF_SYMTAB ".symtab" /* symbol table */ +#define ELF_SYMTAB_SHNDX ".symtab_shndx"/* symbol table section index */ +#define ELF_TBSS ".tbss" /* thread local uninit data */ +#define ELF_TDATA ".tdata" /* thread local init data */ +#define ELF_TDATA1 ".tdata1" /* thread local init data */ +#define ELF_TEXT ".text" /* code */ + +/* Section Attribute Flags - sh_flags */ +#define SHF_WRITE 0x1 /* Writable */ +#define SHF_ALLOC 0x2 /* occupies memory */ +#define SHF_EXECINSTR 0x4 /* executable */ +#define SHF_MERGE 0x10 /* Might be merged */ +#define SHF_STRINGS 0x20 /* Contains NULL terminated strings */ +#define SHF_INFO_LINK 0x40 /* sh_info contains SHT index */ +#define SHF_LINK_ORDER 0x80 /* Preserve order after combining*/ +#define SHF_OS_NONCONFORMING 0x100 /* Non-standard OS specific handling */ +#define SHF_GROUP 0x200 /* Member of section group */ +#define SHF_TLS 0x400 /* Thread local storage */ +#define SHF_MASKOS 0x0ff00000 /* OS specific */ +#define SHF_MASKPROC 0xf0000000 /* reserved bits for processor */ + /* specific section attributes */ + +/* Section Group Flags */ +#define GRP_COMDAT 0x1 /* COMDAT group */ +#define GRP_MASKOS 0x0ff00000 /* Mask OS specific flags */ +#define GRP_MASKPROC 0xf0000000 /* Mask processor specific flags */ + +/* Symbol Table Entry */ +typedef struct elf32_sym { + Elf32_Word st_name; /* name - index into string table */ + Elf32_Addr st_value; /* symbol value */ + Elf32_Word st_size; /* symbol size */ + unsigned char st_info; /* type and binding */ + unsigned char st_other; /* 0 - no defined meaning */ + Elf32_Half st_shndx; /* section header index */ +} Elf32_Sym; + +/* Symbol table index */ +#define STN_UNDEF 0 /* undefined */ + +/* Extract symbol info - st_info */ +#define ELF32_ST_BIND(x) ((x) >> 4) +#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf) +#define ELF32_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf)) +#define ELF32_ST_VISIBILITY(x) ((x) & 0x3) + +/* Symbol Binding - ELF32_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_NUM 3 /* number of symbol bindings */ +#define STB_LOOS 10 /* reserved range for operating */ +#define STB_HIOS 12 /* system specific symbol bindings */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific symbol bindings */ + +/* Symbol type - ELF32_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* not specified */ +#define STT_OBJECT 1 /* data object */ +#define STT_FUNC 2 /* function */ +#define STT_SECTION 3 /* section */ +#define STT_FILE 4 /* file */ +#define STT_NUM 5 /* number of symbol types */ +#define STT_TLS 6 /* Thread local storage symbol */ +#define STT_LOOS 10 /* reserved range for operating */ +#define STT_HIOS 12 /* system specific symbol types */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific symbol types */ + +/* Symbol visibility - ELF32_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0 /* Normal visibility rules */ +#define STV_INTERNAL 1 /* Processor specific hidden class */ +#define STV_HIDDEN 2 /* Symbol unavailable in other mods */ +#define STV_PROTECTED 3 /* Not preemptible, not exported */ + + +/* Relocation entry with implicit addend */ +typedef struct +{ + Elf32_Addr r_offset; /* offset of relocation */ + Elf32_Word r_info; /* symbol table index and type */ +} Elf32_Rel; + +/* Relocation entry with explicit addend */ +typedef struct +{ + Elf32_Addr r_offset; /* offset of relocation */ + Elf32_Word r_info; /* symbol table index and type */ + Elf32_Sword r_addend; +} Elf32_Rela; + +/* Extract relocation info - r_info */ +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((unsigned char) (i)) +#define ELF32_R_INFO(s,t) (((s) << 8) + (unsigned char)(t)) + +/* Program Header */ +typedef struct { + Elf32_Word p_type; /* segment type */ + Elf32_Off p_offset; /* segment offset */ + Elf32_Addr p_vaddr; /* virtual address of segment */ + Elf32_Addr p_paddr; /* physical address - ignored? */ + Elf32_Word p_filesz; /* number of bytes in file for seg. */ + Elf32_Word p_memsz; /* number of bytes in mem. for seg. */ + Elf32_Word p_flags; /* flags */ + Elf32_Word p_align; /* memory alignment */ +} Elf32_Phdr; + +/* Segment types - p_type */ +#define PT_NULL 0 /* unused */ +#define PT_LOAD 1 /* loadable segment */ +#define PT_DYNAMIC 2 /* dynamic linking section */ +#define PT_INTERP 3 /* the RTLD */ +#define PT_NOTE 4 /* auxiliary information */ +#define PT_SHLIB 5 /* reserved - purpose undefined */ +#define PT_PHDR 6 /* program header */ +#define PT_TLS 7 /* Thread local storage template */ +#define PT_NUM 8 /* Number of segment types */ +#define PT_LOOS 0x60000000 /* reserved range for operating */ +#define PT_HIOS 0x6fffffff /* system specific segment types */ +#define PT_LOPROC 0x70000000 /* reserved range for processor */ +#define PT_HIPROC 0x7fffffff /* specific segment types */ + +/* Segment flags - p_flags */ +#define PF_X 0x1 /* Executable */ +#define PF_W 0x2 /* Writable */ +#define PF_R 0x4 /* Readable */ +#define PF_MASKOS 0x0ff00000 /* OS specific segment flags */ +#define PF_MASKPROC 0xf0000000 /* reserved bits for processor */ + /* specific segment flags */ +/* Dynamic structure */ +typedef struct +{ + Elf32_Sword d_tag; /* controls meaning of d_val */ + union + { + Elf32_Word d_val; /* Multiple meanings - see d_tag */ + Elf32_Addr d_ptr; /* program virtual address */ + } d_un; +} Elf32_Dyn; + +extern Elf32_Dyn _DYNAMIC[]; + +/* Dynamic Array Tags - d_tag */ +#define DT_NULL 0 /* marks end of _DYNAMIC array */ +#define DT_NEEDED 1 /* string table offset of needed lib */ +#define DT_PLTRELSZ 2 /* size of relocation entries in PLT */ +#define DT_PLTGOT 3 /* address PLT/GOT */ +#define DT_HASH 4 /* address of symbol hash table */ +#define DT_STRTAB 5 /* address of string table */ +#define DT_SYMTAB 6 /* address of symbol table */ +#define DT_RELA 7 /* address of relocation table */ +#define DT_RELASZ 8 /* size of relocation table */ +#define DT_RELAENT 9 /* size of relocation entry */ +#define DT_STRSZ 10 /* size of string table */ +#define DT_SYMENT 11 /* size of symbol table entry */ +#define DT_INIT 12 /* address of initialization func. */ +#define DT_FINI 13 /* address of termination function */ +#define DT_SONAME 14 /* string table offset of shared obj */ +#define DT_RPATH 15 /* string table offset of library + search path */ +#define DT_SYMBOLIC 16 /* start sym search in shared obj. */ +#define DT_REL 17 /* address of rel. tbl. w addends */ +#define DT_RELSZ 18 /* size of DT_REL relocation table */ +#define DT_RELENT 19 /* size of DT_REL relocation entry */ +#define DT_PLTREL 20 /* PLT referenced relocation entry */ +#define DT_DEBUG 21 /* bugger */ +#define DT_TEXTREL 22 /* Allow rel. mod. to unwritable seg */ +#define DT_JMPREL 23 /* add. of PLT's relocation entries */ +#define DT_BIND_NOW 24 /* Process relocations of object */ +#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ +#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ +#define DT_RUNPATH 29 /* Library search path */ +#define DT_FLAGS 30 /* Flags for the object being loaded */ +#define DT_ENCODING 32 /* Start of encoded range */ +#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ +#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ +#define DT_NUM 34 /* Number used. */ +#define DT_LOOS 0x60000000 /* reserved range for OS */ +#define DT_HIOS 0x6fffffff /* specific dynamic array tags */ +#define DT_LOPROC 0x70000000 /* reserved range for processor */ +#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */ + +/* Dynamic Tag Flags - d_un.d_val */ +#define DF_ORIGIN 0x01 /* Object may use DF_ORIGIN */ +#define DF_SYMBOLIC 0x02 /* Symbol resolutions starts here */ +#define DF_TEXTREL 0x04 /* Object contains text relocations */ +#define DF_BIND_NOW 0x08 /* No lazy binding for this object */ +#define DF_STATIC_TLS 0x10 /* Static thread local storage */ + +/* Standard ELF hashing function */ +unsigned long elf_hash(const unsigned char *name); + +#define ELF_TARG_VER 1 /* The ver for which this code is intended */ + +/* + * XXX - PowerPC defines really don't belong in here, + * but we'll put them in for simplicity. + */ + +/* Values for Elf32/64_Ehdr.e_flags. */ +#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ + +/* Cygnus local bits below */ +#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ +#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib + flag */ + +/* PowerPC relocations defined by the ABIs */ +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 /* 32bit absolute address */ +#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ +#define R_PPC_ADDR16 3 /* 16bit absolute address */ +#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ +#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ +#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ +#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 /* PC relative 26 bit */ +#define R_PPC_REL14 11 /* PC relative 16 bit */ +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 +/* Keep this the last entry. */ +#define R_PPC_NUM 37 + +/* The remaining relocs are from the Embedded ELF ABI, and are not + in the SVR4 ELF ABI. */ +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ + +/* Diab tool relocations. */ +#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ +#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ +#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ +#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ +#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ +#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ + +/* This is a phony reloc to handle any old fashioned TOC16 references + that may still be in object files. */ +#define R_PPC_TOC16 255 + +#endif /* _ELF_H */ diff --git a/src/utils/logger.h b/src/utils/logger.h new file mode 100644 index 0000000..bc85221 --- /dev/null +++ b/src/utils/logger.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) +#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__) + +#define DEBUG_FUNCTION_LINE(FMT, ARGS...)do { \ + WHBLogPrintf("[%23s]%30s@L%04d: " FMT "",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \ + } while (0) + +#ifdef __cplusplus +} +#endif