mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-15 16:05:10 +01:00
*Fixed crash with loading .iso files
*Fixed freeze in theme menu when its empty *Optimized the game list loading on fat/ntfs/ext. This should speed up the loading process. *Added cache of game titles. This will speed up the startup after the cache file is written (in other words on second start of this rev). A TitlesCache.bin will be created in the same path as the wiitdb.xml for this. This should especial speed up the startup of fat/ntfs/ext partitions by a lot if no sub folders with the game titles are used, like GAMEID.wbfs only. That must have been painfully slow before on a lot of games. Should be at about the same speed as with sub folders now. I would still recommend to use sub folders. *Removed wiilight (disc slot) blinking when switching USB port on Hermes cIOSes (thanks rodries) *Added the ehcmodule sources from rodries to the branches *Updated language files
This commit is contained in:
parent
037edbe7ea
commit
0e7d37b18b
45
HBC/META.XML
45
HBC/META.XML
@ -1,45 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
||||||
<app version="1">
|
|
||||||
<name> USB Loader GX</name>
|
|
||||||
<coder>USB Loader GX Team</coder>
|
|
||||||
<version>2.0 r1069</version>
|
|
||||||
<release_date>201102061836</release_date>
|
|
||||||
<no_ios_reload/>
|
|
||||||
<short_description>Loads games from USB-devices</short_description>
|
|
||||||
<long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times.
|
|
||||||
The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller.
|
|
||||||
Features are automatic widescreen detection, coverdownload, parental control, theme support and many more.
|
|
||||||
|
|
||||||
Credits:
|
|
||||||
Coding: Dimok, nIxx, giantpune, ardi, Hungyip84, DrayX7, Lustar, r-win, WiiShizzza
|
|
||||||
Artworks: cyrex, NeoRame
|
|
||||||
WiiTDB / Hosting covers: Lustar
|
|
||||||
Hosting updates files: CorneliousJD
|
|
||||||
USBLoader sources: Waninkoko, Kwiirk, Hermes
|
|
||||||
Languages files updates: Kinyo and translaters
|
|
||||||
Hosting themes: Deak Phreak
|
|
||||||
|
|
||||||
Libwiigui: Tantric
|
|
||||||
Libogc/Devkit: Shagkur and Wintermute
|
|
||||||
FreeTypeGX: Armin Tamzarian.
|
|
||||||
|
|
||||||
Links:
|
|
||||||
USB Loader GX Project Page and Support Site:
|
|
||||||
http://code.google.com/p/usbloader-gui/
|
|
||||||
Help Website:
|
|
||||||
http://usbloadergx.koureio.net/
|
|
||||||
WiiTDB Site:
|
|
||||||
http://wiitdb.com
|
|
||||||
Themes Site:
|
|
||||||
http://wii.spiffy360.com
|
|
||||||
Languages Translaters Page:
|
|
||||||
http://gbatemp.net/index.php?showtopic=155252
|
|
||||||
|
|
||||||
Libwiigui Website:
|
|
||||||
http://wiibrew.org/wiki/Libwiigui/
|
|
||||||
FreeTypeGX Project Page:
|
|
||||||
http://code.google.com/p/freetypegx/
|
|
||||||
Gettext Official Page:
|
|
||||||
http://www.gnu.org/software/gettext/gettext.html
|
|
||||||
</long_description>
|
|
||||||
</app>
|
|
BIN
HBC/icon.png
BIN
HBC/icon.png
Binary file not shown.
Before Width: | Height: | Size: 7.8 KiB |
BIN
HBC/icon2.png
BIN
HBC/icon2.png
Binary file not shown.
Before Width: | Height: | Size: 7.7 KiB |
1078
HBC/readMii.txt
1078
HBC/readMii.txt
File diff suppressed because it is too large
Load Diff
1551
Languages/czech.lang
1551
Languages/czech.lang
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1854
Languages/dutch.lang
1854
Languages/dutch.lang
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1758
Languages/thai.lang
1758
Languages/thai.lang
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,12 +0,0 @@
|
|||||||
#
|
|
||||||
# to use this file rename Make.config.default to Make.config
|
|
||||||
# or create a new Make.config
|
|
||||||
#
|
|
||||||
# you can here add defines
|
|
||||||
#
|
|
||||||
# in example i have included a switch to diseble
|
|
||||||
# the gecko-debug stuff. so also in source gecko.c+gecko.h
|
|
||||||
#
|
|
||||||
# NOTE when add, remove or change a define here then a "make clean" is needed
|
|
||||||
#
|
|
||||||
CFLAGS += -DNO_DEBUG DDEBUG_WBFS
|
|
281
Makefile
281
Makefile
@ -1,281 +0,0 @@
|
|||||||
#---------------------------------------------------------------------------------
|
|
||||||
# Clear the implicit built in rules
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
.SUFFIXES:
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
ifeq ($(strip $(DEVKITPPC)),)
|
|
||||||
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
|
|
||||||
endif
|
|
||||||
|
|
||||||
include $(DEVKITPPC)/wii_rules
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# TARGET is the name of the output
|
|
||||||
# BUILD is the directory where object files & intermediate files will be placed
|
|
||||||
# SOURCES is a list of directories containing source code
|
|
||||||
# INCLUDES is a list of directories containing extra header files
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
TARGET := boot
|
|
||||||
BUILD := build
|
|
||||||
SOURCES := source \
|
|
||||||
source/libwiigui \
|
|
||||||
source/images \
|
|
||||||
source/fonts \
|
|
||||||
source/sounds \
|
|
||||||
source/Controls \
|
|
||||||
source/system \
|
|
||||||
source/libs/libwbfs \
|
|
||||||
source/language \
|
|
||||||
source/mload \
|
|
||||||
source/mload/modules \
|
|
||||||
source/patches \
|
|
||||||
source/usbloader \
|
|
||||||
source/xml \
|
|
||||||
source/network \
|
|
||||||
source/settings \
|
|
||||||
source/settings/menus \
|
|
||||||
source/prompts \
|
|
||||||
source/wad \
|
|
||||||
source/banner \
|
|
||||||
source/BoxCover \
|
|
||||||
source/cheats \
|
|
||||||
source/homebrewboot \
|
|
||||||
source/themes \
|
|
||||||
source/menu \
|
|
||||||
source/memory \
|
|
||||||
source/FileOperations \
|
|
||||||
source/ImageOperations \
|
|
||||||
source/SoundOperations \
|
|
||||||
source/utils \
|
|
||||||
source/utils/minizip \
|
|
||||||
source/usbloader/wbfs
|
|
||||||
DATA := data
|
|
||||||
INCLUDES := source
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# options for code generation
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
CFLAGS = -g -O3 -Wall -Wno-multichar -Wno-unused-parameter -Wextra $(MACHDEP) $(INCLUDE)
|
|
||||||
CXXFLAGS = -Xassembler -aln=$@.lst $(CFLAGS)
|
|
||||||
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map,--section-start,.init=0x80B00000,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,malloc_usable_size
|
|
||||||
-include $(PROJECTDIR)/Make.config
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# any extra libraries we wish to link with the project
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
LIBS := -lpngu -lpng -lgd -lm -lz -lwiiuse -lbte -lasnd -logc -lfreetype -lvorbisidec \
|
|
||||||
-lmad -lmxml -ljpeg -lzip -lcustomfat -lcustomntfs -lcustomext2fs
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# list of directories containing libraries, this must be the top level containing
|
|
||||||
# include and lib
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
LIBDIRS := $(DEVKITPPC)/lib $(CURDIR)
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# 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
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
SVNREV := $(shell bash ./svnrev.sh)
|
|
||||||
export CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
|
||||||
export CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
|
||||||
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
|
||||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
|
||||||
ELFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.elf)))
|
|
||||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.bin)))
|
|
||||||
TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf)))
|
|
||||||
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
|
|
||||||
OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg)))
|
|
||||||
PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm)))
|
|
||||||
WAVFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.wav)))
|
|
||||||
DOLFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.dol)))
|
|
||||||
MP3FILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.mp3)))
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# use CXX for linking C++ projects, CC for standard C
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
ifeq ($(strip $(CPPFILES)),)
|
|
||||||
export LD := $(CC)
|
|
||||||
else
|
|
||||||
export LD := $(CXX)
|
|
||||||
endif
|
|
||||||
|
|
||||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
|
||||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
|
||||||
$(sFILES:.s=.o) $(SFILES:.S=.o) \
|
|
||||||
$(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) $(addsuffix .o,$(DOLFILES))\
|
|
||||||
$(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o) $(MP3FILES:.mp3=.mp3.o) \
|
|
||||||
$(WAVFILES:.wav=.wav.o) $(addsuffix .o,$(ELFFILES)) $(CURDIR)/data/magic_patcher.o
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# build a list of include paths
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
|
||||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
|
||||||
-I$(CURDIR)/$(BUILD) \
|
|
||||||
-I$(LIBOGC_INC)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# build a list of library paths
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) -L$(CURDIR)/source/libs/libfat/ \
|
|
||||||
-L$(CURDIR)/source/libs/libntfs/ -L$(CURDIR)/source/libs/libext2fs/ \
|
|
||||||
-L$(LIBOGC_LIB)
|
|
||||||
|
|
||||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
|
||||||
.PHONY: $(BUILD) lang all clean
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
$(BUILD):
|
|
||||||
@[ -d $@ ] || mkdir -p $@
|
|
||||||
@/bin/bash ./buildtype.sh
|
|
||||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
|
||||||
# @echo debug...
|
|
||||||
# start geckoreader.exe
|
|
||||||
|
|
||||||
channel:
|
|
||||||
@[ -d build ] || mkdir -p build
|
|
||||||
@/bin/bash ./buildtype.sh FULLCHANNEL
|
|
||||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
lang:
|
|
||||||
@[ -d build ] || mkdir -p build
|
|
||||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile language
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
theme:
|
|
||||||
@[ -d build ] || mkdir -p build
|
|
||||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile language
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
all:
|
|
||||||
@[ -d build ] || mkdir -p build
|
|
||||||
@./buildtype.sh
|
|
||||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
|
||||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile language
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
clean:
|
|
||||||
@echo clean ...
|
|
||||||
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
run:
|
|
||||||
$(MAKE)
|
|
||||||
@echo Done building ...
|
|
||||||
@echo Now Run That Shit ...
|
|
||||||
|
|
||||||
wiiload $(OUTPUT).dol
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
reload:
|
|
||||||
wiiload -r $(OUTPUT).dol
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
release:
|
|
||||||
$(MAKE)
|
|
||||||
cp boot.dol ./hbc/boot.dol
|
|
||||||
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
else
|
|
||||||
|
|
||||||
DEPENDS := $(OFILES:.o=.d)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# main targets
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
$(OUTPUT).dol: $(OUTPUT).elf
|
|
||||||
$(OUTPUT).elf: $(OFILES)
|
|
||||||
|
|
||||||
language: $(wildcard $(PROJECTDIR)/Languages/*.lang) $(wildcard $(PROJECTDIR)/Themes/*.them)
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# This rule links in binary data with .ttf, .png, and .mp3 extensions
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
%.elf.o : %.elf
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
%.dol.o : %.dol
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
%.ttf.o : %.ttf
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
%.png.o : %.png
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
%.ogg.o : %.ogg
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
%.pcm.o : %.pcm
|
|
||||||
@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 $(@)
|
|
||||||
|
|
||||||
%.certs.o : %.certs
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
%.dat.o : %.dat
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
%.bin.o : %.bin
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
%.tik.o : %.tik
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
%.tmd.o : %.tmd
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export PATH := $(PROJECTDIR)/gettext-bin:$(PATH)
|
|
||||||
|
|
||||||
%.pot: $(CFILES) $(CPPFILES)
|
|
||||||
@echo Updating Languagefiles ...
|
|
||||||
@touch $(PROJECTDIR)/Languages/$(TARGET).pot
|
|
||||||
@xgettext -C -cTRANSLATORS --from-code=utf-8 --sort-output --no-wrap --no-location -ktr -ktrNOOP -o$(PROJECTDIR)/Languages/$(TARGET).pot -p $@ $^
|
|
||||||
@echo Updating Themefiles ...
|
|
||||||
@touch $(PROJECTDIR)/Themes/$(TARGET).pot
|
|
||||||
@xgettext -C -cTRANSLATORS --from-code=utf-8 -F --no-wrap --add-location -kthInt -kthColor -kthAlign -o$(PROJECTDIR)/Themes/$(TARGET).pot -p $@ $^
|
|
||||||
|
|
||||||
%.lang: $(PROJECTDIR)/Languages/$(TARGET).pot
|
|
||||||
@msgmerge -U -N --no-wrap --no-location --backup=none -q $@ $<
|
|
||||||
@touch $@
|
|
||||||
|
|
||||||
%.them: $(PROJECTDIR)/Themes/$(TARGET).pot
|
|
||||||
@msgmerge -U -N --no-wrap --no-location --backup=none -q $@ $<
|
|
||||||
@touch $@
|
|
||||||
|
|
||||||
-include $(DEPENDS)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
endif
|
|
||||||
#---------------------------------------------------------------------------------
|
|
@ -1,431 +0,0 @@
|
|||||||
# USB Loader GX theme source file.
|
|
||||||
# don't delete/change this line (é).
|
|
||||||
# ONLY the value before the '-' char needs to be entered in msgstr ""
|
|
||||||
# not the complete text.
|
|
||||||
# It is important that the image folder is defined for the images to load.
|
|
||||||
# The image folder should be in the same folder as the .them file and include the theme images.
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: USB Loader GX\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2011-01-20 15:51+0100\n"
|
|
||||||
"PO-Revision-Date: 2009-10-01 01:00+0200\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=utf-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Theme-Title: Example\n"
|
|
||||||
"Image-Folder: Example\n"
|
|
||||||
"Last-Themer: Example\n"
|
|
||||||
"Theme-Team: Example\n"
|
|
||||||
"Theme-Version: Example\n"
|
|
||||||
|
|
||||||
msgid "r=0 g=0 b=0 a=255 - prompt windows text color"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "r=0 g=0 b=0 a=255 - settings text color"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "9 - game list browser page size"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "r=0 g=0 b=0 a=255 - game browser list text color"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "r=0 g=0 b=0 a=255 - game browser list text color over"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "left - carousel layout left arrow align hor"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "top - carousel layout left arrow align ver"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "20 - carousel layout left arrow pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "65 - carousel layout left arrow pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "right - carousel layout right arrow align hor"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "top - carousel layout right arrow align ver"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "-20 - carousel layout right arrow pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "65 - carousel layout right arrow pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "r=55 g=190 b=237 a=255 - carousel game name text color"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "0 - game grid layout pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "20 - game grid layout pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "255 - tooltip alpha"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "r=55 g=190 b=237 a=255 - hdd info color"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "center - hdd info align hor"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "top - hdd info align ver"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "0 - hdd info pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "400 - hdd info pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "r=55 g=190 b=237 a=255 - game count color"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "center - game count align hor"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "top - game count align ver"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "0 - game count pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "420 - game count pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "16 - install btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "355 - install btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "371 - settings btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "64 - settings btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "371 - home menu btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "489 - home menu btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "355 - power off btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "576 - power off btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "160 - sd card btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "395 - sd card btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "405 - HBC btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "410 - HBC btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "26 - cover/download btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "58 - cover/download btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "305 - gameID btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "68 - gameID btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "r=138 g=138 b=138 a=240 - clock color"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "left - clock align hor"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "top - clock align ver"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "275 - clock pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "335 - clock pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "260 - list layout favorite btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "288 - list layout favorite btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - list layout favorite btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "300 - list layout search btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "320 - list layout search btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - list layout search btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "340 - list layout abc/sort btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "352 - list layout abc/sort btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - list layout abc/sort btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "380 - list layout list btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "384 - list layout list btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - list layout list btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "416 - list layout grid btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "420 - list layout grid btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - list layout grid btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "448 - list layout carousel btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "460 - list layout carousel btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - list layout carousel btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "480 - list layout lock btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "500 - list layout lock btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - list layout lock btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "512 - list layout dvd btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "540 - list layout dvd btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - list layout dvd btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "280 - game list layout height"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "396 - game list layout width"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "200 - game list layout pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "49 - game list layout pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "200 - grid layout favorite btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "224 - grid layout favorite btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - grid layout favorite btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "240 - grid layout search btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "256 - grid layout search btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - grid layout search btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "280 - grid layout abc/sort btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "288 - grid layout abc/sort btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - grid layout abc/sort btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "320 - grid layout list btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "320 - grid layout list btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - grid layout list btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "352 - grid layout grid btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "360 - grid layout grid btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - grid layout grid btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "384 - grid layout carousel btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "400 - grid layout carousel btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - grid layout carousel btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "416 - grid layout lock btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "440 - grid layout lock btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - grid layout lock btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "448 - grid layout dvd btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "480 - grid layout dvd btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - grid layout dvd btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "400 - game grid layout height"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "640 - game grid layout width"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "200 - carousel layout favorite btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "224 - carousel layout favorite btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - carousel layout favorite btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "240 - carousel layout search btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "256 - carousel layout search btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - carousel layout search btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "280 - carousel layout abc/sort btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "288 - carousel layout abc/sort btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - carousel layout abc/sort btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "320 - carousel layout list btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "320 - carousel layout list btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - carousel layout list btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "352 - carousel layout grid btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "360 - carousel layout grid btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - carousel layout grid btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "384 - carousel layout carousel btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "400 - carousel layout carousel btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - carousel layout carousel btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "416 - carousel layout lock btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "440 - carousel layout lock btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - carousel layout lock btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "448 - carousel layout dvd btn pos x widescreen"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "480 - carousel layout dvd btn pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "13 - carousel layout dvd btn pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "400 - game carousel layout height"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "640 - game carousel layout width"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "-20 - game carousel layout pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "0 - game carousel layout pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "1 - show hdd info: 1 for on and 0 for off"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "1 - show game count: 1 for on and 0 for off"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "r=55 g=190 b=237 a=255 - game id text color"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "r=55 g=190 b=237 a=255 - region info text color"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "30 - region info text pos y"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "68 - region info text pos x"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "1 - Enable tooltips: 0 for off and 1 for on"
|
|
||||||
msgstr ""
|
|
14
buildtype.sh
14
buildtype.sh
@ -1,14 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [ ! -z "$1" ];
|
|
||||||
then
|
|
||||||
if [ ! -s source/buildtype.h ];
|
|
||||||
then
|
|
||||||
echo "#define $1" > source/buildtype.h
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if [[ ! -f source/buildtype.h || -s source/buildtype.h ]];
|
|
||||||
then
|
|
||||||
cp /dev/null source/buildtype.h
|
|
||||||
fi
|
|
||||||
fi
|
|
BIN
cios_installer.dol
Normal file
BIN
cios_installer.dol
Normal file
Binary file not shown.
After Width: | Height: | Size: 352 KiB |
339
cios_installer/COPYING
Normal file
339
cios_installer/COPYING
Normal file
@ -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.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
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.
|
5
cios_installer/MakeIt.bat
Normal file
5
cios_installer/MakeIt.bat
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
|
make
|
||||||
|
|
||||||
|
pause
|
141
cios_installer/Makefile
Normal file
141
cios_installer/Makefile
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# Clear the implicit built in rules
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(DEVKITPPC)),)
|
||||||
|
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC)
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(DEVKITPPC)/wii_rules
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# TARGET is the name of the output
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# INCLUDES is a list of directories containing extra header files
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
TARGET := cios_installer
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := .
|
||||||
|
DATA := data
|
||||||
|
INCLUDES :=
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) $(DEBUG) $(ADD_DIP_PLUGIN)
|
||||||
|
CXXFLAGS = $(CFLAGS)
|
||||||
|
|
||||||
|
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# any extra libraries we wish to link with the project
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBS := -lwiiuse -lbte -lm -lfat -logc -ldb
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
# include and lib
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS :=
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
|
||||||
|
export 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 := $(addsuffix .o,$(BINFILES)) \
|
||||||
|
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
||||||
|
$(sFILES:.s=.o) $(SFILES:.S=.o)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# build a list of include paths
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(CURDIR)/$(BUILD) \
|
||||||
|
-I$(LIBOGC_INC)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# build a list of library paths
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
|
||||||
|
-L$(LIBOGC_LIB)
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
.PHONY: $(BUILD) clean
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(BUILD):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
upload:
|
||||||
|
$(DEVKITPPC)/bin/geckoupload $(TARGET).dol; nanokdp -d /dev/tty.usbserial-GECKUSB0
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(OUTPUT).dol: $(OUTPUT).elf
|
||||||
|
$(OUTPUT).elf: $(OFILES)
|
||||||
|
|
||||||
|
%.certs.o : %.certs
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
%.elf.o : %.elf
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
%.bin.o : %.bin
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
%.raw.o : %.raw
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------
|
BIN
cios_installer/data/mload.elf
Normal file
BIN
cios_installer/data/mload.elf
Normal file
Binary file not shown.
7
cios_installer/debug_printf.h
Normal file
7
cios_installer/debug_printf.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef _DEBUG_PRINTF_H_
|
||||||
|
#define _DEBUG_PRINTF_H_
|
||||||
|
|
||||||
|
void debug_printf(const char *fmt, ...);
|
||||||
|
void error_debug_printf(const char *fmt, ...);
|
||||||
|
|
||||||
|
#endif
|
57
cios_installer/elf.h
Normal file
57
cios_installer/elf.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/* Copyright (C) 2008 Mega Man */
|
||||||
|
#ifndef __ELF_H_
|
||||||
|
#define __ELF_H_
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
/* File header */
|
||||||
|
typedef struct Elf32_Ehdr
|
||||||
|
{
|
||||||
|
uint32_t magic; /* Magic number */
|
||||||
|
unsigned char info[12]; /* other info */
|
||||||
|
uint16_t type; /* Object file type */
|
||||||
|
uint16_t machine; /* Architecture */
|
||||||
|
uint32_t version; /* Object file version */
|
||||||
|
uint32_t entry; /* Entry point virtual address */
|
||||||
|
uint32_t phoff; /* Program header table file offset */
|
||||||
|
uint32_t shoff; /* Section header table file offset */
|
||||||
|
uint32_t flags; /* Processor-specific flags */
|
||||||
|
uint16_t ehsize; /* ELF header size in bytes */
|
||||||
|
uint16_t phentsize; /* Program header table entry size */
|
||||||
|
uint16_t phnum; /* Program header table entry count */
|
||||||
|
uint16_t shentsize; /* Section header table entry size */
|
||||||
|
uint16_t shnum; /* Section header table entry count */
|
||||||
|
uint16_t shstrndx; /* Section header string table index */
|
||||||
|
} Elf32_Ehdr_t;
|
||||||
|
|
||||||
|
/* Conglomeration of the identification bytes, for easy testing as a word. */
|
||||||
|
#if 0
|
||||||
|
/** ELF magic for little endian. */
|
||||||
|
#define ELFMAGIC 0x464c457f
|
||||||
|
#else
|
||||||
|
/** ELF magic for big endian. */
|
||||||
|
#define ELFMAGIC 0x7f454c46
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Program segment header. */
|
||||||
|
typedef struct Elf32_Phdr
|
||||||
|
{
|
||||||
|
uint32_t type; /* type */
|
||||||
|
uint32_t offset; /* file offset */
|
||||||
|
uint32_t vaddr; /* virtual address */
|
||||||
|
uint32_t paddr; /* physical address */
|
||||||
|
uint32_t filesz; /* size in file */
|
||||||
|
uint32_t memsz; /* size in memory */
|
||||||
|
uint32_t flags; /* flags */
|
||||||
|
uint32_t align; /* alignment */
|
||||||
|
} Elf32_Phdr_t;
|
||||||
|
|
||||||
|
/* Possible values for segment type. */
|
||||||
|
#define PT_LOAD 1 /* Loadable program segment */
|
||||||
|
|
||||||
|
/* Possible values for segment flags. */
|
||||||
|
#define PF_X 1 /* executable */
|
||||||
|
#define PF_W 2 /* writable */
|
||||||
|
#define PF_R 4 /* readable */
|
||||||
|
|
||||||
|
#endif /* __ELF_H_ */
|
397
cios_installer/http.c
Normal file
397
cios_installer/http.c
Normal file
@ -0,0 +1,397 @@
|
|||||||
|
/* http -- http convenience functions
|
||||||
|
|
||||||
|
Copyright (C) 2008 bushing
|
||||||
|
|
||||||
|
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, version 2.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <network.h>
|
||||||
|
#include <ogc/lwp_watchdog.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
void debug_printf(const char *fmt, ...);
|
||||||
|
|
||||||
|
#include "http.h"
|
||||||
|
|
||||||
|
char *http_host;
|
||||||
|
u16 http_port;
|
||||||
|
char *http_path;
|
||||||
|
u32 http_max_size;
|
||||||
|
|
||||||
|
http_res result;
|
||||||
|
u32 http_status;
|
||||||
|
u32 content_length;
|
||||||
|
u8 *http_data;
|
||||||
|
|
||||||
|
s32 tcp_socket (void) {
|
||||||
|
s32 s, res;
|
||||||
|
|
||||||
|
s = net_socket (PF_INET, SOCK_STREAM, 0);
|
||||||
|
if (s < 0) {
|
||||||
|
debug_printf ("net_socket failed: %d\n", s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = net_fcntl (s, F_GETFL, 0);
|
||||||
|
if (res < 0) {
|
||||||
|
debug_printf ("F_GETFL failed: %d\n", res);
|
||||||
|
net_close (s);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = net_fcntl (s, F_SETFL, res | 4);
|
||||||
|
if (res < 0) {
|
||||||
|
debug_printf ("F_SETFL failed: %d\n", res);
|
||||||
|
net_close (s);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 tcp_connect (char *host, const u16 port) {
|
||||||
|
struct hostent *hp;
|
||||||
|
struct sockaddr_in sa;
|
||||||
|
s32 s, res;
|
||||||
|
s64 t;
|
||||||
|
|
||||||
|
hp = net_gethostbyname (host);
|
||||||
|
if (!hp || !(hp->h_addrtype == PF_INET)) {
|
||||||
|
debug_printf ("net_gethostbyname failed: %d\n", errno);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = tcp_socket ();
|
||||||
|
if (s < 0)
|
||||||
|
return s;
|
||||||
|
|
||||||
|
memset (&sa, 0, sizeof (struct sockaddr_in));
|
||||||
|
sa.sin_family= PF_INET;
|
||||||
|
sa.sin_len = sizeof (struct sockaddr_in);
|
||||||
|
sa.sin_port= htons (port);
|
||||||
|
memcpy ((char *) &sa.sin_addr, hp->h_addr_list[0], hp->h_length);
|
||||||
|
|
||||||
|
t = gettime ();
|
||||||
|
while (true) {
|
||||||
|
if (ticks_to_millisecs (diff_ticks (t, gettime ())) >
|
||||||
|
TCP_CONNECT_TIMEOUT) {
|
||||||
|
debug_printf ("tcp_connect timeout\n");
|
||||||
|
net_close (s);
|
||||||
|
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = net_connect (s, (struct sockaddr *) &sa,
|
||||||
|
sizeof (struct sockaddr_in));
|
||||||
|
|
||||||
|
if (res < 0) {
|
||||||
|
if (res == -EISCONN)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (res == -EINPROGRESS || res == -EALREADY) {
|
||||||
|
usleep (20 * 1000);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_printf ("net_connect failed: %d\n", res);
|
||||||
|
net_close (s);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * tcp_readln (const s32 s, const u16 max_length, const u64 start_time, const u32 timeout) {
|
||||||
|
char *buf;
|
||||||
|
u16 c;
|
||||||
|
s32 res;
|
||||||
|
char *ret;
|
||||||
|
|
||||||
|
buf = (char *) malloc (max_length);
|
||||||
|
|
||||||
|
c = 0;
|
||||||
|
ret = NULL;
|
||||||
|
while (true) {
|
||||||
|
if (ticks_to_millisecs (diff_ticks (start_time, gettime ())) > timeout)
|
||||||
|
break;
|
||||||
|
|
||||||
|
res = net_read (s, &buf[c], 1);
|
||||||
|
|
||||||
|
if ((res == 0) || (res == -EAGAIN)) {
|
||||||
|
usleep (20 * 1000);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res < 0) {
|
||||||
|
debug_printf ("tcp_readln failed: %d\n", res);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((c > 0) && (buf[c - 1] == '\r') && (buf[c] == '\n')) {
|
||||||
|
if (c == 1) {
|
||||||
|
ret = strdup ("");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = strndup (buf, c - 1);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
c++;
|
||||||
|
|
||||||
|
if (c == max_length)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free (buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tcp_read (const s32 s, u8 **buffer, const u32 length) {
|
||||||
|
u8 *p;
|
||||||
|
u32 step, left, block, received;
|
||||||
|
s64 t;
|
||||||
|
s32 res;
|
||||||
|
|
||||||
|
step = 0;
|
||||||
|
p = *buffer;
|
||||||
|
left = length;
|
||||||
|
received = 0;
|
||||||
|
|
||||||
|
t = gettime ();
|
||||||
|
while (left) {
|
||||||
|
if (ticks_to_millisecs (diff_ticks (t, gettime ())) >
|
||||||
|
TCP_BLOCK_RECV_TIMEOUT) {
|
||||||
|
debug_printf ("tcp_read timeout\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
block = left;
|
||||||
|
if (block > (32*1024))
|
||||||
|
block = (32*1024);
|
||||||
|
|
||||||
|
res = net_read (s, p, block);
|
||||||
|
|
||||||
|
if ((res == 0) || (res == -EAGAIN)) {
|
||||||
|
usleep (20 * 1000);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res < 0) {
|
||||||
|
debug_printf ("net_read failed: %d\n", res);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
received += res;
|
||||||
|
left -= res;
|
||||||
|
p += res;
|
||||||
|
|
||||||
|
if ((received / TCP_BLOCK_SIZE) > step) {
|
||||||
|
t = gettime ();
|
||||||
|
step++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return left == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tcp_write (const s32 s, const u8 *buffer, const u32 length) {
|
||||||
|
const u8 *p;
|
||||||
|
u32 step, left, block, sent;
|
||||||
|
s64 t;
|
||||||
|
s32 res;
|
||||||
|
|
||||||
|
step = 0;
|
||||||
|
p = buffer;
|
||||||
|
left = length;
|
||||||
|
sent = 0;
|
||||||
|
|
||||||
|
t = gettime ();
|
||||||
|
while (left) {
|
||||||
|
if (ticks_to_millisecs (diff_ticks (t, gettime ())) >
|
||||||
|
TCP_BLOCK_SEND_TIMEOUT) {
|
||||||
|
|
||||||
|
debug_printf ("tcp_write timeout\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
block = left;
|
||||||
|
if (block > 2048)
|
||||||
|
block = 2048;
|
||||||
|
|
||||||
|
res = net_write (s, p, block);
|
||||||
|
|
||||||
|
if ((res == 0) || (res == -56)) {
|
||||||
|
usleep (20 * 1000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res < 0) {
|
||||||
|
debug_printf ("net_write failed: %d\n", res);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sent += res;
|
||||||
|
left -= res;
|
||||||
|
p += res;
|
||||||
|
|
||||||
|
if ((sent / TCP_BLOCK_SIZE) > step) {
|
||||||
|
t = gettime ();
|
||||||
|
step++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return left == 0;
|
||||||
|
}
|
||||||
|
bool http_split_url (char **host, char **path, const char *url) {
|
||||||
|
const char *p;
|
||||||
|
char *c;
|
||||||
|
|
||||||
|
if (strncasecmp (url, "http://", 7))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
p = url + 7;
|
||||||
|
c = strchr (p, '/');
|
||||||
|
|
||||||
|
if (c[0] == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*host = strndup (p, c - p);
|
||||||
|
*path = strdup (c);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool http_request (const char *url, const u32 max_size) {
|
||||||
|
int linecount;
|
||||||
|
if (!http_split_url(&http_host, &http_path, url)) return false;
|
||||||
|
|
||||||
|
http_port = 80;
|
||||||
|
http_max_size = max_size;
|
||||||
|
|
||||||
|
http_status = 404;
|
||||||
|
content_length = 0;
|
||||||
|
http_data = NULL;
|
||||||
|
|
||||||
|
int s = tcp_connect (http_host, http_port);
|
||||||
|
// debug_printf("tcp_connect(%s, %hu) = %d\n", http_host, http_port, s);
|
||||||
|
if (s < 0) {
|
||||||
|
result = HTTPR_ERR_CONNECT;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *request = (char *) malloc (1024);
|
||||||
|
char *r = request;
|
||||||
|
r += sprintf (r, "GET %s HTTP/1.1\r\n", http_path);
|
||||||
|
r += sprintf (r, "Host: %s\r\n", http_host);
|
||||||
|
r += sprintf (r, "Cache-Control: no-cache\r\n\r\n");
|
||||||
|
|
||||||
|
// debug_printf("request = %s\n", request);
|
||||||
|
|
||||||
|
bool b = tcp_write (s, (u8 *) request, strlen (request));
|
||||||
|
// debug_printf("tcp_write returned %d\n", b);
|
||||||
|
|
||||||
|
free (request);
|
||||||
|
linecount = 0;
|
||||||
|
|
||||||
|
for (linecount=0; linecount < 32; linecount++) {
|
||||||
|
char *line = tcp_readln (s, 0xff, gettime(), HTTP_TIMEOUT);
|
||||||
|
// debug_printf("tcp_readln returned %p (%s)\n", line, line?line:"(null)");
|
||||||
|
if (!line) {
|
||||||
|
http_status = 404;
|
||||||
|
result = HTTPR_ERR_REQUEST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen (line) < 1) {
|
||||||
|
free (line);
|
||||||
|
line = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sscanf (line, "HTTP/1.1 %u", &http_status);
|
||||||
|
sscanf (line, "Content-Length: %u", &content_length);
|
||||||
|
|
||||||
|
free (line);
|
||||||
|
line = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
// debug_printf("content_length = %d, status = %d, linecount = %d\n", content_length, http_status, linecount);
|
||||||
|
if (linecount == 32 || !content_length) http_status = 404;
|
||||||
|
if (http_status != 200) {
|
||||||
|
result = HTTPR_ERR_STATUS;
|
||||||
|
net_close (s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (content_length > http_max_size) {
|
||||||
|
result = HTTPR_ERR_TOOBIG;
|
||||||
|
net_close (s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
http_data = (u8 *) malloc (content_length);
|
||||||
|
b = tcp_read (s, &http_data, content_length);
|
||||||
|
if (!b) {
|
||||||
|
free (http_data);
|
||||||
|
http_data = NULL;
|
||||||
|
result = HTTPR_ERR_RECEIVE;
|
||||||
|
net_close (s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = HTTPR_OK;
|
||||||
|
|
||||||
|
net_close (s);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool http_get_result (u32 *_http_status, u8 **content, u32 *length) {
|
||||||
|
if (http_status) *_http_status = http_status;
|
||||||
|
|
||||||
|
if (result == HTTPR_OK) {
|
||||||
|
*content = http_data;
|
||||||
|
*length = content_length;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
*content = NULL;
|
||||||
|
*length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
free (http_host);
|
||||||
|
free (http_path);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
32
cios_installer/http.h
Normal file
32
cios_installer/http.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef _HTTP_H_
|
||||||
|
#define _HTTP_H_
|
||||||
|
|
||||||
|
#include <gctypes.h>
|
||||||
|
#define TCP_CONNECT_TIMEOUT 10000
|
||||||
|
#define TCP_BLOCK_SIZE (8 * 1024)
|
||||||
|
#define TCP_BLOCK_RECV_TIMEOUT 10000
|
||||||
|
#define TCP_BLOCK_SEND_TIMEOUT 10000
|
||||||
|
|
||||||
|
s32 tcp_socket (void);
|
||||||
|
s32 tcp_connect (char *host, const u16 port);
|
||||||
|
|
||||||
|
char * tcp_readln (const s32 s, const u16 max_length, const u64 start_time, const u32 timeout);
|
||||||
|
bool tcp_read (const s32 s, u8 **buffer, const u32 length);
|
||||||
|
bool tcp_write (const s32 s, const u8 *buffer, const u32 length);
|
||||||
|
|
||||||
|
#define HTTP_TIMEOUT 300000
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
HTTPR_OK,
|
||||||
|
HTTPR_ERR_CONNECT,
|
||||||
|
HTTPR_ERR_REQUEST,
|
||||||
|
HTTPR_ERR_STATUS,
|
||||||
|
HTTPR_ERR_TOOBIG,
|
||||||
|
HTTPR_ERR_RECEIVE
|
||||||
|
} http_res;
|
||||||
|
|
||||||
|
bool http_request (const char *url, const u32 max_size);
|
||||||
|
bool http_get_result (u32 *http_status, u8 **content, u32 *length);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
1618
cios_installer/patchmii_core.c
Normal file
1618
cios_installer/patchmii_core.c
Normal file
File diff suppressed because it is too large
Load Diff
40
cios_installer/patchmii_core.h
Normal file
40
cios_installer/patchmii_core.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Basic I/O.
|
||||||
|
|
||||||
|
static inline u32 read32(u32 addr)
|
||||||
|
{
|
||||||
|
u32 x;
|
||||||
|
asm volatile("lwz %0,0(%1) ; sync" : "=r"(x) : "b"(0xc0000000 | addr));
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void write32(u32 addr, u32 x)
|
||||||
|
{
|
||||||
|
asm("stw %0,0(%1) ; eieio" : : "r"(x), "b"(0xc0000000 | addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
// USB Gecko.
|
||||||
|
|
||||||
|
void usb_flush(int chn);
|
||||||
|
int usb_sendbuffer(int chn,const void *buffer,int size);
|
||||||
|
|
||||||
|
// Version string.
|
||||||
|
|
||||||
|
extern const char version[];
|
||||||
|
|
||||||
|
// Debug: blink the tray led.
|
||||||
|
|
||||||
|
static inline void blink(void)
|
||||||
|
{
|
||||||
|
write32(0x0d8000c0, read32(0x0d8000c0) ^ 0x20);
|
||||||
|
}
|
||||||
|
|
||||||
|
void debug_printf(const char *fmt, ...);
|
||||||
|
void hexdump(void *d, int len);
|
||||||
|
void aes_set_key(u8 *key);
|
||||||
|
void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len);
|
||||||
|
void aes_encrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len);
|
||||||
|
|
||||||
|
#define TRACE(x) debug_printf("%s / %d: %d\n", __FUNCTION__, __LINE__, (x))
|
||||||
|
|
||||||
|
#define ISFS_ACCESS_READ 1
|
||||||
|
#define ISFS_ACCESS_WRITE 2
|
60
cios_installer/replace_ios_modules.c
Normal file
60
cios_installer/replace_ios_modules.c
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <gccore.h>
|
||||||
|
|
||||||
|
//#define OH0_REPL
|
||||||
|
#ifdef OH0_REPL
|
||||||
|
#include "oh0_elf.h"
|
||||||
|
#endif
|
||||||
|
struct ios_module_replacement
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
u8 *data;
|
||||||
|
u32 *size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ios_module_replacement ios_repls[]={
|
||||||
|
#ifdef OH0_REPL
|
||||||
|
{"OH0",(u8*)oh0_elf,(u32*)&oh0_elf_size}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
void debug_printf(const char *fmt, ...);
|
||||||
|
|
||||||
|
int replace_ios_modules(u8 **decrypted_buf, u32 *content_size)
|
||||||
|
{
|
||||||
|
int i,version;
|
||||||
|
u32 len;
|
||||||
|
u8*buf = *decrypted_buf;
|
||||||
|
char *ios_version_tag = "$IOSVersion:";
|
||||||
|
len = *content_size;
|
||||||
|
if (len == 64)
|
||||||
|
return 0;
|
||||||
|
version =0;
|
||||||
|
for (i=0; i<(len-64); i++)
|
||||||
|
if (!strncmp((char *)buf+i, ios_version_tag, 10)) {
|
||||||
|
version = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<sizeof(ios_repls)/sizeof(ios_repls[0]); i++){
|
||||||
|
struct ios_module_replacement *repl = &ios_repls[i];
|
||||||
|
if(!memcmp(buf+version+13,repl->name,strlen(repl->name)))
|
||||||
|
{
|
||||||
|
debug_printf("replaced %s\n",repl->name);
|
||||||
|
free(*decrypted_buf);
|
||||||
|
len = *repl->size;
|
||||||
|
len+=31;
|
||||||
|
len&=~31;
|
||||||
|
*decrypted_buf = malloc(len);
|
||||||
|
memcpy(*decrypted_buf,repl->data,len);
|
||||||
|
*content_size = len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
398
cios_installer/rijndael.c
Normal file
398
cios_installer/rijndael.c
Normal file
@ -0,0 +1,398 @@
|
|||||||
|
/* Rijndael Block Cipher - rijndael.c
|
||||||
|
|
||||||
|
Written by Mike Scott 21st April 1999
|
||||||
|
mike@compapp.dcu.ie
|
||||||
|
|
||||||
|
Permission for free direct or derivative use is granted subject
|
||||||
|
to compliance with any conditions that the originators of the
|
||||||
|
algorithm place on its exploitation.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define u8 unsigned char /* 8 bits */
|
||||||
|
#define u32 unsigned long /* 32 bits */
|
||||||
|
#define u64 unsigned long long
|
||||||
|
|
||||||
|
/* rotates x one bit to the left */
|
||||||
|
|
||||||
|
#define ROTL(x) (((x)>>7)|((x)<<1))
|
||||||
|
|
||||||
|
/* Rotates 32-bit word left by 1, 2 or 3 byte */
|
||||||
|
|
||||||
|
#define ROTL8(x) (((x)<<8)|((x)>>24))
|
||||||
|
#define ROTL16(x) (((x)<<16)|((x)>>16))
|
||||||
|
#define ROTL24(x) (((x)<<24)|((x)>>8))
|
||||||
|
|
||||||
|
/* Fixed Data */
|
||||||
|
|
||||||
|
static u8 InCo[4]={0xB,0xD,0x9,0xE}; /* Inverse Coefficients */
|
||||||
|
|
||||||
|
static u8 fbsub[256];
|
||||||
|
static u8 rbsub[256];
|
||||||
|
static u8 ptab[256],ltab[256];
|
||||||
|
static u32 ftable[256];
|
||||||
|
static u32 rtable[256];
|
||||||
|
static u32 rco[30];
|
||||||
|
|
||||||
|
/* Parameter-dependent data */
|
||||||
|
|
||||||
|
int Nk,Nb,Nr;
|
||||||
|
u8 fi[24],ri[24];
|
||||||
|
u32 fkey[120];
|
||||||
|
u32 rkey[120];
|
||||||
|
|
||||||
|
static u32 pack(u8 *b)
|
||||||
|
{ /* pack bytes into a 32-bit Word */
|
||||||
|
return ((u32)b[3]<<24)|((u32)b[2]<<16)|((u32)b[1]<<8)|(u32)b[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unpack(u32 a,u8 *b)
|
||||||
|
{ /* unpack bytes from a word */
|
||||||
|
b[0]=(u8)a;
|
||||||
|
b[1]=(u8)(a>>8);
|
||||||
|
b[2]=(u8)(a>>16);
|
||||||
|
b[3]=(u8)(a>>24);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 xtime(u8 a)
|
||||||
|
{
|
||||||
|
u8 b;
|
||||||
|
if (a&0x80) b=0x1B;
|
||||||
|
else b=0;
|
||||||
|
a<<=1;
|
||||||
|
a^=b;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 bmul(u8 x,u8 y)
|
||||||
|
{ /* x.y= AntiLog(Log(x) + Log(y)) */
|
||||||
|
if (x && y) return ptab[(ltab[x]+ltab[y])%255];
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 SubByte(u32 a)
|
||||||
|
{
|
||||||
|
u8 b[4];
|
||||||
|
unpack(a,b);
|
||||||
|
b[0]=fbsub[b[0]];
|
||||||
|
b[1]=fbsub[b[1]];
|
||||||
|
b[2]=fbsub[b[2]];
|
||||||
|
b[3]=fbsub[b[3]];
|
||||||
|
return pack(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 product(u32 x,u32 y)
|
||||||
|
{ /* dot product of two 4-byte arrays */
|
||||||
|
u8 xb[4],yb[4];
|
||||||
|
unpack(x,xb);
|
||||||
|
unpack(y,yb);
|
||||||
|
return bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 InvMixCol(u32 x)
|
||||||
|
{ /* matrix Multiplication */
|
||||||
|
u32 y,m;
|
||||||
|
u8 b[4];
|
||||||
|
|
||||||
|
m=pack(InCo);
|
||||||
|
b[3]=product(m,x);
|
||||||
|
m=ROTL24(m);
|
||||||
|
b[2]=product(m,x);
|
||||||
|
m=ROTL24(m);
|
||||||
|
b[1]=product(m,x);
|
||||||
|
m=ROTL24(m);
|
||||||
|
b[0]=product(m,x);
|
||||||
|
y=pack(b);
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 ByteSub(u8 x)
|
||||||
|
{
|
||||||
|
u8 y=ptab[255-ltab[x]]; /* multiplicative inverse */
|
||||||
|
x=y; x=ROTL(x);
|
||||||
|
y^=x; x=ROTL(x);
|
||||||
|
y^=x; x=ROTL(x);
|
||||||
|
y^=x; x=ROTL(x);
|
||||||
|
y^=x; y^=0x63;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gentables(void)
|
||||||
|
{ /* generate tables */
|
||||||
|
int i;
|
||||||
|
u8 y,b[4];
|
||||||
|
|
||||||
|
/* use 3 as primitive root to generate power and log tables */
|
||||||
|
|
||||||
|
ltab[0]=0;
|
||||||
|
ptab[0]=1; ltab[1]=0;
|
||||||
|
ptab[1]=3; ltab[3]=1;
|
||||||
|
for (i=2;i<256;i++)
|
||||||
|
{
|
||||||
|
ptab[i]=ptab[i-1]^xtime(ptab[i-1]);
|
||||||
|
ltab[ptab[i]]=i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* affine transformation:- each bit is xored with itself shifted one bit */
|
||||||
|
|
||||||
|
fbsub[0]=0x63;
|
||||||
|
rbsub[0x63]=0;
|
||||||
|
for (i=1;i<256;i++)
|
||||||
|
{
|
||||||
|
y=ByteSub((u8)i);
|
||||||
|
fbsub[i]=y; rbsub[y]=i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0,y=1;i<30;i++)
|
||||||
|
{
|
||||||
|
rco[i]=y;
|
||||||
|
y=xtime(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate forward and reverse tables */
|
||||||
|
for (i=0;i<256;i++)
|
||||||
|
{
|
||||||
|
y=fbsub[i];
|
||||||
|
b[3]=y^xtime(y); b[2]=y;
|
||||||
|
b[1]=y; b[0]=xtime(y);
|
||||||
|
ftable[i]=pack(b);
|
||||||
|
|
||||||
|
y=rbsub[i];
|
||||||
|
b[3]=bmul(InCo[0],y); b[2]=bmul(InCo[1],y);
|
||||||
|
b[1]=bmul(InCo[2],y); b[0]=bmul(InCo[3],y);
|
||||||
|
rtable[i]=pack(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gkey(int nb,int nk,char *key)
|
||||||
|
{ /* blocksize=32*nb bits. Key=32*nk bits */
|
||||||
|
/* currently nb,bk = 4, 6 or 8 */
|
||||||
|
/* key comes as 4*Nk bytes */
|
||||||
|
/* Key Scheduler. Create expanded encryption key */
|
||||||
|
int i,j,k,m,N;
|
||||||
|
int C1,C2,C3;
|
||||||
|
u32 CipherKey[8];
|
||||||
|
|
||||||
|
Nb=nb; Nk=nk;
|
||||||
|
|
||||||
|
/* Nr is number of rounds */
|
||||||
|
if (Nb>=Nk) Nr=6+Nb;
|
||||||
|
else Nr=6+Nk;
|
||||||
|
|
||||||
|
C1=1;
|
||||||
|
if (Nb<8) { C2=2; C3=3; }
|
||||||
|
else { C2=3; C3=4; }
|
||||||
|
|
||||||
|
/* pre-calculate forward and reverse increments */
|
||||||
|
for (m=j=0;j<nb;j++,m+=3)
|
||||||
|
{
|
||||||
|
fi[m]=(j+C1)%nb;
|
||||||
|
fi[m+1]=(j+C2)%nb;
|
||||||
|
fi[m+2]=(j+C3)%nb;
|
||||||
|
ri[m]=(nb+j-C1)%nb;
|
||||||
|
ri[m+1]=(nb+j-C2)%nb;
|
||||||
|
ri[m+2]=(nb+j-C3)%nb;
|
||||||
|
}
|
||||||
|
|
||||||
|
N=Nb*(Nr+1);
|
||||||
|
|
||||||
|
for (i=j=0;i<Nk;i++,j+=4)
|
||||||
|
{
|
||||||
|
CipherKey[i]=pack((u8 *)&key[j]);
|
||||||
|
}
|
||||||
|
for (i=0;i<Nk;i++) fkey[i]=CipherKey[i];
|
||||||
|
for (j=Nk,k=0;j<N;j+=Nk,k++)
|
||||||
|
{
|
||||||
|
fkey[j]=fkey[j-Nk]^SubByte(ROTL24(fkey[j-1]))^rco[k];
|
||||||
|
if (Nk<=6)
|
||||||
|
{
|
||||||
|
for (i=1;i<Nk && (i+j)<N;i++)
|
||||||
|
fkey[i+j]=fkey[i+j-Nk]^fkey[i+j-1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i=1;i<4 &&(i+j)<N;i++)
|
||||||
|
fkey[i+j]=fkey[i+j-Nk]^fkey[i+j-1];
|
||||||
|
if ((j+4)<N) fkey[j+4]=fkey[j+4-Nk]^SubByte(fkey[j+3]);
|
||||||
|
for (i=5;i<Nk && (i+j)<N;i++)
|
||||||
|
fkey[i+j]=fkey[i+j-Nk]^fkey[i+j-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now for the expanded decrypt key in reverse order */
|
||||||
|
|
||||||
|
for (j=0;j<Nb;j++) rkey[j+N-Nb]=fkey[j];
|
||||||
|
for (i=Nb;i<N-Nb;i+=Nb)
|
||||||
|
{
|
||||||
|
k=N-Nb-i;
|
||||||
|
for (j=0;j<Nb;j++) rkey[k+j]=InvMixCol(fkey[i+j]);
|
||||||
|
}
|
||||||
|
for (j=N-Nb;j<N;j++) rkey[j-N+Nb]=fkey[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* There is an obvious time/space trade-off possible here. *
|
||||||
|
* Instead of just one ftable[], I could have 4, the other *
|
||||||
|
* 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */
|
||||||
|
|
||||||
|
void encrypt(char *buff)
|
||||||
|
{
|
||||||
|
int i,j,k,m;
|
||||||
|
u32 a[8],b[8],*x,*y,*t;
|
||||||
|
|
||||||
|
for (i=j=0;i<Nb;i++,j+=4)
|
||||||
|
{
|
||||||
|
a[i]=pack((u8 *)&buff[j]);
|
||||||
|
a[i]^=fkey[i];
|
||||||
|
}
|
||||||
|
k=Nb;
|
||||||
|
x=a; y=b;
|
||||||
|
|
||||||
|
/* State alternates between a and b */
|
||||||
|
for (i=1;i<Nr;i++)
|
||||||
|
{ /* Nr is number of rounds. May be odd. */
|
||||||
|
|
||||||
|
/* if Nb is fixed - unroll this next
|
||||||
|
loop and hard-code in the values of fi[] */
|
||||||
|
|
||||||
|
for (m=j=0;j<Nb;j++,m+=3)
|
||||||
|
{ /* deal with each 32-bit element of the State */
|
||||||
|
/* This is the time-critical bit */
|
||||||
|
y[j]=fkey[k++]^ftable[(u8)x[j]]^
|
||||||
|
ROTL8(ftable[(u8)(x[fi[m]]>>8)])^
|
||||||
|
ROTL16(ftable[(u8)(x[fi[m+1]]>>16)])^
|
||||||
|
ROTL24(ftable[x[fi[m+2]]>>24]);
|
||||||
|
}
|
||||||
|
t=x; x=y; y=t; /* swap pointers */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Last Round - unroll if possible */
|
||||||
|
for (m=j=0;j<Nb;j++,m+=3)
|
||||||
|
{
|
||||||
|
y[j]=fkey[k++]^(u32)fbsub[(u8)x[j]]^
|
||||||
|
ROTL8((u32)fbsub[(u8)(x[fi[m]]>>8)])^
|
||||||
|
ROTL16((u32)fbsub[(u8)(x[fi[m+1]]>>16)])^
|
||||||
|
ROTL24((u32)fbsub[x[fi[m+2]]>>24]);
|
||||||
|
}
|
||||||
|
for (i=j=0;i<Nb;i++,j+=4)
|
||||||
|
{
|
||||||
|
unpack(y[i],(u8 *)&buff[j]);
|
||||||
|
x[i]=y[i]=0; /* clean up stack */
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void decrypt(char *buff)
|
||||||
|
{
|
||||||
|
int i,j,k,m;
|
||||||
|
u32 a[8],b[8],*x,*y,*t;
|
||||||
|
|
||||||
|
for (i=j=0;i<Nb;i++,j+=4)
|
||||||
|
{
|
||||||
|
a[i]=pack((u8 *)&buff[j]);
|
||||||
|
a[i]^=rkey[i];
|
||||||
|
}
|
||||||
|
k=Nb;
|
||||||
|
x=a; y=b;
|
||||||
|
|
||||||
|
/* State alternates between a and b */
|
||||||
|
for (i=1;i<Nr;i++)
|
||||||
|
{ /* Nr is number of rounds. May be odd. */
|
||||||
|
|
||||||
|
/* if Nb is fixed - unroll this next
|
||||||
|
loop and hard-code in the values of ri[] */
|
||||||
|
|
||||||
|
for (m=j=0;j<Nb;j++,m+=3)
|
||||||
|
{ /* This is the time-critical bit */
|
||||||
|
y[j]=rkey[k++]^rtable[(u8)x[j]]^
|
||||||
|
ROTL8(rtable[(u8)(x[ri[m]]>>8)])^
|
||||||
|
ROTL16(rtable[(u8)(x[ri[m+1]]>>16)])^
|
||||||
|
ROTL24(rtable[x[ri[m+2]]>>24]);
|
||||||
|
}
|
||||||
|
t=x; x=y; y=t; /* swap pointers */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Last Round - unroll if possible */
|
||||||
|
for (m=j=0;j<Nb;j++,m+=3)
|
||||||
|
{
|
||||||
|
y[j]=rkey[k++]^(u32)rbsub[(u8)x[j]]^
|
||||||
|
ROTL8((u32)rbsub[(u8)(x[ri[m]]>>8)])^
|
||||||
|
ROTL16((u32)rbsub[(u8)(x[ri[m+1]]>>16)])^
|
||||||
|
ROTL24((u32)rbsub[x[ri[m+2]]>>24]);
|
||||||
|
}
|
||||||
|
for (i=j=0;i<Nb;i++,j+=4)
|
||||||
|
{
|
||||||
|
unpack(y[i],(u8 *)&buff[j]);
|
||||||
|
x[i]=y[i]=0; /* clean up stack */
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void aes_set_key(u8 *key) {
|
||||||
|
gentables();
|
||||||
|
gkey(4, 4,(void*) key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CBC mode decryption
|
||||||
|
void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len) {
|
||||||
|
u8 block[16];
|
||||||
|
unsigned int blockno = 0, i;
|
||||||
|
|
||||||
|
// debug_printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
|
||||||
|
|
||||||
|
for (blockno = 0; blockno <= (len / sizeof(block)); blockno++) {
|
||||||
|
unsigned int fraction;
|
||||||
|
if (blockno == (len / sizeof(block))) { // last block
|
||||||
|
fraction = len % sizeof(block);
|
||||||
|
if (fraction == 0) break;
|
||||||
|
memset((void *) block, 0, sizeof(block));
|
||||||
|
} else fraction = 16;
|
||||||
|
|
||||||
|
// debug_printf("block %d: fraction = %d\n", blockno, fraction);
|
||||||
|
memcpy((void *) block, inbuf + blockno * sizeof(block), fraction);
|
||||||
|
decrypt((void *) block);
|
||||||
|
u8 *ctext_ptr;
|
||||||
|
if (blockno == 0) ctext_ptr = iv;
|
||||||
|
else ctext_ptr = inbuf + (blockno-1) * sizeof(block);
|
||||||
|
|
||||||
|
for(i=0; i < fraction; i++)
|
||||||
|
outbuf[blockno * sizeof(block) + i] =
|
||||||
|
ctext_ptr[i] ^ block[i];
|
||||||
|
// debug_printf("Block %d output: ", blockno);
|
||||||
|
// hexdump(outbuf + blockno*sizeof(block), 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CBC mode encryption
|
||||||
|
void aes_encrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len) {
|
||||||
|
u8 block[16];
|
||||||
|
unsigned int blockno = 0, i;
|
||||||
|
|
||||||
|
// debug_printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
|
||||||
|
|
||||||
|
for (blockno = 0; blockno <= (len / sizeof(block)); blockno++) {
|
||||||
|
unsigned int fraction;
|
||||||
|
if (blockno == (len / sizeof(block))) { // last block
|
||||||
|
fraction = len % sizeof(block);
|
||||||
|
if (fraction == 0) break;
|
||||||
|
memset((void *) block, 0, sizeof(block));
|
||||||
|
} else fraction = 16;
|
||||||
|
|
||||||
|
// debug_printf("block %d: fraction = %d\n", blockno, fraction);
|
||||||
|
memcpy(block, inbuf + blockno * sizeof(block), fraction);
|
||||||
|
|
||||||
|
for(i=0; i < fraction; i++)
|
||||||
|
block[i] = inbuf[blockno * sizeof(block) + i] ^ iv[i];
|
||||||
|
|
||||||
|
encrypt((void *) block);
|
||||||
|
memcpy(iv, block, sizeof(block));
|
||||||
|
memcpy(outbuf + blockno * sizeof(block), block, sizeof(block));
|
||||||
|
// debug_printf("Block %d output: ", blockno);
|
||||||
|
// hexdump(outbuf + blockno*sizeof(block), 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
78
cios_installer/runtime_ios_patch.c
Normal file
78
cios_installer/runtime_ios_patch.c
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2010 Joseph Jordan <joe.ftpii@psychlaw.com.au>
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2;
|
||||||
|
// see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||||
|
|
||||||
|
// Some modifications taken from dop-mii. Credits to them
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <ogc/machine/processor.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "runtime_ios_patch.h"
|
||||||
|
|
||||||
|
#define MEM_REG_BASE 0xd8b4000
|
||||||
|
#define MEM_PROT (MEM_REG_BASE + 0x20a)
|
||||||
|
|
||||||
|
static void disable_memory_protection() {
|
||||||
|
write32(MEM_PROT, read32(MEM_PROT) & 0x0000FFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 apply_patch(char *name, const u8 *old, u32 old_size, const u8 *patch, u32 patch_size, u32 patch_offset) {
|
||||||
|
u8 *ptr = (u8 *)0x93400000;
|
||||||
|
u32 found = 0;
|
||||||
|
u8 *location = NULL;
|
||||||
|
while ((u32)ptr < (0x94000000 - patch_size)) {
|
||||||
|
if (!memcmp(ptr, old, old_size)) {
|
||||||
|
found++;
|
||||||
|
location = ptr + patch_offset;
|
||||||
|
u8 *start = location;
|
||||||
|
u32 i;
|
||||||
|
for (i = 0; i < patch_size; i++) {
|
||||||
|
*location++ = patch[i];
|
||||||
|
}
|
||||||
|
DCFlushRange((u8 *)(((u32)start) >> 5 << 5), (patch_size >> 5 << 5) + 64);
|
||||||
|
ICInvalidateRange((u8 *)(((u32)start) >> 5 << 5), (patch_size >> 5 << 5) + 64);
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
if (found) {
|
||||||
|
printf("\b..");
|
||||||
|
} else {
|
||||||
|
printf("\b!.");
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const u8 di_readlimit_old[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0A, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x7E, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08
|
||||||
|
};
|
||||||
|
static const u8 di_readlimit_patch[] = { 0x7e, 0xd4 };
|
||||||
|
|
||||||
|
const u8 isfs_permissions_old[] = { 0x42, 0x8B, 0xD0, 0x01, 0x25, 0x66 };
|
||||||
|
const u8 isfs_permissions_patch[] = { 0x42, 0x8B, 0xE0, 0x01, 0x25, 0x66 };
|
||||||
|
static const u8 setuid_old[] = { 0xD1, 0x2A, 0x1C, 0x39 };
|
||||||
|
static const u8 setuid_patch[] = { 0x46, 0xC0 };
|
||||||
|
const u8 es_identify_old[] = { 0x28, 0x03, 0xD1, 0x23 };
|
||||||
|
const u8 es_identify_patch[] = { 0x00, 0x00 };
|
||||||
|
const u8 hash_old[] = { 0x20, 0x07, 0x23, 0xA2 };
|
||||||
|
const u8 hash_patch[] = { 0x00 };
|
||||||
|
const u8 new_hash_old[] = { 0x20, 0x07, 0x4B, 0x0B };
|
||||||
|
|
||||||
|
u32 IOSPATCH_Apply() {
|
||||||
|
printf("\n\n");
|
||||||
|
u32 count = 0;
|
||||||
|
if (HAVE_AHBPROT) {
|
||||||
|
disable_memory_protection();
|
||||||
|
count += apply_patch("di_readlimit", di_readlimit_old, sizeof(di_readlimit_old), di_readlimit_patch, sizeof(di_readlimit_patch), 12);
|
||||||
|
count += apply_patch("isfs_permissions", isfs_permissions_old, sizeof(isfs_permissions_old), isfs_permissions_patch, sizeof(isfs_permissions_patch), 0);
|
||||||
|
count += apply_patch("es_setuid", setuid_old, sizeof(setuid_old), setuid_patch, sizeof(setuid_patch), 0);
|
||||||
|
count += apply_patch("es_identify", es_identify_old, sizeof(es_identify_old), es_identify_patch, sizeof(es_identify_patch), 2);
|
||||||
|
count += apply_patch("hash_check", hash_old, sizeof(hash_old), hash_patch, sizeof(hash_patch), 1);
|
||||||
|
count += apply_patch("new_hash_check", new_hash_old, sizeof(new_hash_old), hash_patch, sizeof(hash_patch), 1);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
14
cios_installer/runtime_ios_patch.h
Normal file
14
cios_installer/runtime_ios_patch.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2010 Joseph Jordan <joe.ftpii@psychlaw.com.au>
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2;
|
||||||
|
// see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||||
|
|
||||||
|
#ifndef __RUNTIMEIOSPATCH_H
|
||||||
|
#define __RUNTIMEIOSPATCH_H
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
|
||||||
|
#define HAVE_AHBPROT ((*(vu32*)0xcd800064 == 0xFFFFFFFF) ? 1 : 0)
|
||||||
|
|
||||||
|
u32 IOSPATCH_Apply();
|
||||||
|
|
||||||
|
#endif
|
172
cios_installer/sha1.c
Normal file
172
cios_installer/sha1.c
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
SHA-1 in C
|
||||||
|
By Steve Reid <steve@edmweb.com>
|
||||||
|
100% Public Domain
|
||||||
|
|
||||||
|
Test Vectors (from FIPS PUB 180-1)
|
||||||
|
"abc"
|
||||||
|
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
|
||||||
|
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||||
|
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
|
||||||
|
A million repetitions of "a"
|
||||||
|
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #define LITTLE_ENDIAN * This should be #define'd if true. */
|
||||||
|
#define SHA1HANDSOFF
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "sha1.h"
|
||||||
|
|
||||||
|
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||||
|
|
||||||
|
/* blk0() and blk() perform the initial expand. */
|
||||||
|
/* I got the idea of expanding during the round function from SSLeay */
|
||||||
|
#ifdef LITTLE_ENDIAN
|
||||||
|
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|
||||||
|
|(rol(block->l[i],8)&0x00FF00FF))
|
||||||
|
#else
|
||||||
|
#define blk0(i) block->l[i]
|
||||||
|
#endif
|
||||||
|
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
|
||||||
|
^block->l[(i+2)&15]^block->l[i&15],1))
|
||||||
|
|
||||||
|
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||||
|
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||||
|
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||||
|
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
|
||||||
|
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
|
||||||
|
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
|
||||||
|
|
||||||
|
|
||||||
|
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||||
|
|
||||||
|
void SHA1Transform(unsigned long state[5], unsigned char buffer[64])
|
||||||
|
{
|
||||||
|
unsigned long a, b, c, d, e;
|
||||||
|
typedef union {
|
||||||
|
unsigned char c[64];
|
||||||
|
unsigned long l[16];
|
||||||
|
} CHAR64LONG16;
|
||||||
|
CHAR64LONG16* block;
|
||||||
|
#ifdef SHA1HANDSOFF
|
||||||
|
static unsigned char workspace[64];
|
||||||
|
block = (CHAR64LONG16*)workspace;
|
||||||
|
memcpy(block, buffer, 64);
|
||||||
|
#else
|
||||||
|
block = (CHAR64LONG16*)buffer;
|
||||||
|
#endif
|
||||||
|
/* Copy context->state[] to working vars */
|
||||||
|
a = state[0];
|
||||||
|
b = state[1];
|
||||||
|
c = state[2];
|
||||||
|
d = state[3];
|
||||||
|
e = state[4];
|
||||||
|
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||||
|
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
||||||
|
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
||||||
|
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
|
||||||
|
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
|
||||||
|
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
|
||||||
|
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
|
||||||
|
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
|
||||||
|
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
|
||||||
|
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
|
||||||
|
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
|
||||||
|
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
|
||||||
|
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
|
||||||
|
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
|
||||||
|
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
|
||||||
|
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
|
||||||
|
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
|
||||||
|
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
|
||||||
|
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
|
||||||
|
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
|
||||||
|
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
|
||||||
|
/* Add the working vars back into context.state[] */
|
||||||
|
state[0] += a;
|
||||||
|
state[1] += b;
|
||||||
|
state[2] += c;
|
||||||
|
state[3] += d;
|
||||||
|
state[4] += e;
|
||||||
|
/* Wipe variables */
|
||||||
|
a = b = c = d = e = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* SHA1Init - Initialize new context */
|
||||||
|
|
||||||
|
void SHA1Init(SHA1_CTX* context)
|
||||||
|
{
|
||||||
|
/* SHA1 initialization constants */
|
||||||
|
context->state[0] = 0x67452301;
|
||||||
|
context->state[1] = 0xEFCDAB89;
|
||||||
|
context->state[2] = 0x98BADCFE;
|
||||||
|
context->state[3] = 0x10325476;
|
||||||
|
context->state[4] = 0xC3D2E1F0;
|
||||||
|
context->count[0] = context->count[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Run your data through this. */
|
||||||
|
|
||||||
|
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len)
|
||||||
|
{
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
|
j = (context->count[0] >> 3) & 63;
|
||||||
|
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
|
||||||
|
context->count[1] += (len >> 29);
|
||||||
|
if ((j + len) > 63) {
|
||||||
|
memcpy(&context->buffer[j], data, (i = 64-j));
|
||||||
|
SHA1Transform(context->state, context->buffer);
|
||||||
|
for ( ; i + 63 < len; i += 64) {
|
||||||
|
SHA1Transform(context->state, &data[i]);
|
||||||
|
}
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
else i = 0;
|
||||||
|
memcpy(&context->buffer[j], &data[i], len - i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Add padding and return the message digest. */
|
||||||
|
|
||||||
|
void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
|
||||||
|
{
|
||||||
|
unsigned long i, j;
|
||||||
|
unsigned char finalcount[8];
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
|
||||||
|
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
|
||||||
|
}
|
||||||
|
SHA1Update(context, (unsigned char *)"\200", 1);
|
||||||
|
while ((context->count[0] & 504) != 448) {
|
||||||
|
SHA1Update(context, (unsigned char *)"\0", 1);
|
||||||
|
}
|
||||||
|
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
|
||||||
|
for (i = 0; i < 20; i++) {
|
||||||
|
digest[i] = (unsigned char)
|
||||||
|
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
||||||
|
}
|
||||||
|
/* Wipe variables */
|
||||||
|
i = j = 0;
|
||||||
|
memset(context->buffer, 0, 64);
|
||||||
|
memset(context->state, 0, 20);
|
||||||
|
memset(context->count, 0, 8);
|
||||||
|
memset(&finalcount, 0, 8);
|
||||||
|
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
|
||||||
|
SHA1Transform(context->state, context->buffer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf) {
|
||||||
|
SHA1_CTX ctx;
|
||||||
|
|
||||||
|
SHA1Init(&ctx);
|
||||||
|
SHA1Update(&ctx, ptr, size);
|
||||||
|
SHA1Final(outbuf, &ctx);
|
||||||
|
}
|
||||||
|
|
12
cios_installer/sha1.h
Normal file
12
cios_installer/sha1.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
typedef struct {
|
||||||
|
unsigned long state[5];
|
||||||
|
unsigned long count[2];
|
||||||
|
unsigned char buffer[64];
|
||||||
|
} SHA1_CTX;
|
||||||
|
|
||||||
|
void SHA1Transform(unsigned long state[5], unsigned char buffer[64]);
|
||||||
|
void SHA1Init(SHA1_CTX* context);
|
||||||
|
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len);
|
||||||
|
void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
|
||||||
|
|
||||||
|
void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf);
|
114
cios_installer/tmd_add_module.c
Normal file
114
cios_installer/tmd_add_module.c
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <network.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <wiiuse/wpad.h>
|
||||||
|
|
||||||
|
#include "patchmii_core.h"
|
||||||
|
#include "sha1.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "http.h"
|
||||||
|
//#include "haxx_certs.h"
|
||||||
|
#include <fat.h>
|
||||||
|
//#include "ehc_elf.h"
|
||||||
|
#include "mload_elf.h"
|
||||||
|
|
||||||
|
//#define ADD_EHC
|
||||||
|
|
||||||
|
#define ADD_HAXX // active this if you want to play with starlet without installing 50 times an hour
|
||||||
|
//#define REMOVE_OH0
|
||||||
|
u32 save_nus_object (u16 index, u8 *buf, u32 size);
|
||||||
|
|
||||||
|
/* add module inside the tmd
|
||||||
|
take care of alignement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int INPUT_TITLEID_L;
|
||||||
|
|
||||||
|
void tmd_add_module(tmd *p_tmd,const u8 *elf, u32 elf_size)
|
||||||
|
{
|
||||||
|
int ncid;
|
||||||
|
int i,found=0;
|
||||||
|
tmd_content *p_cr = (tmd_content *)TMD_CONTENTS(p_tmd);
|
||||||
|
sha1 hash;
|
||||||
|
int content_size = (elf_size+31)&~31;
|
||||||
|
u8 *buf = memalign(32,content_size);
|
||||||
|
int index = p_tmd->num_contents;
|
||||||
|
memset((void *) buf,0,content_size);
|
||||||
|
|
||||||
|
memcpy((void *) buf,elf,elf_size);
|
||||||
|
|
||||||
|
|
||||||
|
ncid = 10;
|
||||||
|
while(!found){
|
||||||
|
found = 1;
|
||||||
|
ncid++;
|
||||||
|
for (i=0;i<p_tmd->num_contents;i++) {
|
||||||
|
if(p_cr[i].cid == ncid){ found = 0;break;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_printf("found a free cid: %x\n",ncid);
|
||||||
|
p_cr[index].cid = ncid;
|
||||||
|
p_cr[index].type = 0x0001; // shared is 0x8001
|
||||||
|
p_cr[index].size = content_size;
|
||||||
|
p_cr[index].index = index;
|
||||||
|
|
||||||
|
//calc sha
|
||||||
|
SHA1(buf, content_size, hash);
|
||||||
|
memcpy(p_cr[index].hash, hash, sizeof hash);
|
||||||
|
p_tmd->num_contents++;
|
||||||
|
save_nus_object(ncid, buf, content_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_custom_modules(tmd *p_tmd)
|
||||||
|
{
|
||||||
|
tmd_content tmp;
|
||||||
|
int tmd_dirty=0;
|
||||||
|
tmd_content *p_cr = (tmd_content *)TMD_CONTENTS(p_tmd);
|
||||||
|
#ifdef REMOVE_OH0 // remove oh0 module
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
debug_printf("removing cid %d\n",p_cr[2].cid);
|
||||||
|
memmove(&p_cr[2],&p_cr[3],p_tmd->num_contents*sizeof(tmd_content)-2);
|
||||||
|
p_tmd->num_contents--;
|
||||||
|
for (i=0;i<p_tmd->num_contents;i++)
|
||||||
|
p_cr[i].index = i;
|
||||||
|
tmd_dirty = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef ADD_EHC
|
||||||
|
/* add ehc module. We need it installed before OH0 and OH1, because IOS loads it in the order of the tmd.
|
||||||
|
for some reason, we cant shift all indexes or the IOS_Reload will crashed without saying anything.
|
||||||
|
*/
|
||||||
|
debug_printf("adding EHC module\n");
|
||||||
|
tmd_add_module(p_tmd,ehc_elf,ehc_elf_size);
|
||||||
|
|
||||||
|
tmp = p_cr[3]; // inverse ehc and oh0 place in tmd
|
||||||
|
p_cr[3] = p_cr[p_tmd->num_contents-1];
|
||||||
|
p_cr[p_tmd->num_contents-1] = tmp;
|
||||||
|
tmd_dirty = 1;
|
||||||
|
#endif
|
||||||
|
#ifdef ADD_HAXX
|
||||||
|
/*add haxx module. We need it installed before OH0 and OH1, because IOS loads it in the order of the tmd.
|
||||||
|
for some reason, we cant shift all indexes or the IOS_Reload will crashed without saying anything.
|
||||||
|
*/
|
||||||
|
debug_printf("adding haxx module\n");
|
||||||
|
tmd_add_module(p_tmd,mload_elf,mload_elf_size);
|
||||||
|
|
||||||
|
tmp = p_cr[3-(INPUT_TITLEID_L==57)]; // inverse ehc and oh0 place in tmd
|
||||||
|
p_cr[3-(INPUT_TITLEID_L==57)] = p_cr[p_tmd->num_contents-1];
|
||||||
|
p_cr[p_tmd->num_contents-1] = tmp;
|
||||||
|
|
||||||
|
|
||||||
|
tmd_dirty = 1;
|
||||||
|
#endif
|
||||||
|
return tmd_dirty;
|
||||||
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 104 KiB |
BIN
data/certs.dat
BIN
data/certs.dat
Binary file not shown.
Binary file not shown.
BIN
data/stub.bin
BIN
data/stub.bin
Binary file not shown.
4
ehcmodule/MakeIt.bat
Normal file
4
ehcmodule/MakeIt.bat
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
make
|
||||||
|
|
||||||
|
pause
|
144
ehcmodule/Makefile
Normal file
144
ehcmodule/Makefile
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# Clear the implicit built in rules
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# 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 := $(notdir $(CURDIR))
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := source ../libcios/source ../wii_wbfs
|
||||||
|
DATA := data
|
||||||
|
INCLUDES := include ../tinyehci ../libcios/include ../wii_wbfs
|
||||||
|
SCRIPTDIR := scripts
|
||||||
|
BIN := bin
|
||||||
|
|
||||||
|
STRIPIOS := ../stripios/stripios.exe
|
||||||
|
|
||||||
|
LIBS :=
|
||||||
|
LIBDIRS :=
|
||||||
|
|
||||||
|
export IOS_MODULE=ehc
|
||||||
|
|
||||||
|
CFLAGS+=-D$(IOS_MODULE) $(DEBUG)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# the prefix on the compiler executables
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
#$(DEVKITARM)/bin/
|
||||||
|
PREFIX := $(DEVKITARM)/bin/arm-eabi-
|
||||||
|
CC := $(PREFIX)gcc
|
||||||
|
CXX := $(PREFIX)g++
|
||||||
|
AR := $(PREFIX)ar
|
||||||
|
OBJCOPY := $(PREFIX)objcopy
|
||||||
|
LD := $(PREFIX)g++
|
||||||
|
AS := $(PREFIX)g++
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# linker script
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LINKSCRIPT := $(ROOT)/$(SCRIPTDIR)/link.ld
|
||||||
|
SPECS := $(ROOT)/$(SCRIPTDIR)/nostart.specs
|
||||||
|
|
||||||
|
ifeq ($(BUILDING),$(emptystring))
|
||||||
|
|
||||||
|
export ROOT := $(CURDIR)
|
||||||
|
|
||||||
|
|
||||||
|
all:
|
||||||
|
@[ -d $(BUILD) ] || mkdir -p $(BUILD)
|
||||||
|
@$(MAKE) -C $(BUILD) --no-print-directory -f $(CURDIR)/Makefile BUILDING=all
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(BIN)/*.elf
|
||||||
|
else
|
||||||
|
|
||||||
|
TARGET := $(notdir $(ROOT))
|
||||||
|
STRIPIOS := $(ROOT)/$(STRIPIOS)
|
||||||
|
#----------------------------------------------------
|
||||||
|
# MS Visual Studio Style Fix:
|
||||||
|
#----------------------------------------------------
|
||||||
|
#STYLEFIX = 2>&1 | sed -e 's/\([a-zA-Z\.]\+\):\([0-9]\+\):\([0-9]\+:\)\?\(.\+\)/\1(\2):\4/' -e 's/undefined/error: undefined/'
|
||||||
|
STYLEFIX ?=
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# automatically build a list of object files for our project
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
OUTPUT := $(ROOT)/$(BIN)/$(TARGET)
|
||||||
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.c)))
|
||||||
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.cpp)))
|
||||||
|
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.s)))
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.S)))
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(ROOT)/$(dir)/*.*)))
|
||||||
|
|
||||||
|
OFILES := $(addsuffix _bin.o,$(BINFILES)) \
|
||||||
|
$(CPPFILES:.cpp=_cpp.o) $(CFILES:.c=_c.o) \
|
||||||
|
$(sFILES:.s=_s.o) $(SFILES:.S=_S.o)
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
VPATH = $(foreach dir,$(SOURCES),$(ROOT)/$(dir))
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
INCLUDE := $(foreach dir,$(INCLUDES),-I$(ROOT)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(ROOT)/$(BUILD)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# build a list of library paths
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||||
|
|
||||||
|
ARCH = -mcpu=arm9tdmi -mtune=arm9tdmi -mthumb -mthumb-interwork -mbig-endian
|
||||||
|
|
||||||
|
CFLAGS += -g $(ARCH) $(INCLUDE) -fno-strict-aliasing -Wall -Os -fomit-frame-pointer -ffast-math -fverbose-asm -Wpointer-arith -Winline -Wundef -g -ffunction-sections -fdata-sections -fno-exceptions
|
||||||
|
CFLAGS += -Wstrict-prototypes
|
||||||
|
|
||||||
|
|
||||||
|
AFLAGS = -g $(ARCH) -x assembler-with-cpp
|
||||||
|
|
||||||
|
LDFLAGS = -g $(ARCH) -specs=$(SPECS) -T$(LINKSCRIPT) $(LIBPATHS) $(LIBS) -Wl,--gc-sections -Wl,-static -Wl,-Map,$(TARGET).map -nostartfiles
|
||||||
|
|
||||||
|
|
||||||
|
$(OUTPUT).elf: $(TARGET).elf
|
||||||
|
@echo stripping $(notdir $@)
|
||||||
|
@$(STRIPIOS) $< $@
|
||||||
|
|
||||||
|
|
||||||
|
%.elf: $(OFILES)
|
||||||
|
@echo linking $(notdir $@)
|
||||||
|
@$(LD) -g -o $@ $(OFILES) $(LDFLAGS) $(STYLEFIX)
|
||||||
|
|
||||||
|
|
||||||
|
%_cpp.o : %.cpp
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(CXX) -MMD -MF $*_cpp.d $(CFLAGS) -c $< -o$@ $(STYLEFIX)
|
||||||
|
|
||||||
|
%_c.o : %.c
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(CC) -MMD -MF $*_c.d $(CFLAGS) -c $< -o$@ $(STYLEFIX)
|
||||||
|
|
||||||
|
%_s.o : %.s
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(AS) -MMD -MF $*_s.d $(AFLAGS) -c $< -o$@ $(STYLEFIX)
|
||||||
|
|
||||||
|
%_bin.o : %.bin
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
define bin2o
|
||||||
|
@echo -e "\t.section .rodata\n\t.align 4\n\t.global $(*)\n\t.global $(*)_end\n$(*):\n\t.incbin \"$(subst /,\\\\\\\\,$(shell echo $< | sed 's=/==;s=/=:/='))\"\n$(*)_end:\n" > $@.s
|
||||||
|
@$(CC) $(ASFLAGS) $(AFLAGS) -c $@.s -o $@
|
||||||
|
@rm -rf $@.s
|
||||||
|
endef
|
||||||
|
|
||||||
|
endif
|
11
ehcmodule/bin/convert.bat
Normal file
11
ehcmodule/bin/convert.bat
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
del *.c
|
||||||
|
del *.h
|
||||||
|
filetochar ehcmodule.elf ehcmodule_5 -h -align 32
|
||||||
|
del C:\devkitPro\soft\usbloader\source\mload\modules\ehcmodule_5.c
|
||||||
|
del C:\devkitPro\soft\usbloader\source\mload\modules\ehcmodule_5.h
|
||||||
|
copy ehcmodule_5.c C:\devkitPro\soft\usbloader\source\mload\modules\
|
||||||
|
copy ehcmodule_5.h C:\devkitPro\soft\usbloader\source\mload\modules\
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
BIN
ehcmodule/bin/filetochar.exe
Normal file
BIN
ehcmodule/bin/filetochar.exe
Normal file
Binary file not shown.
30
ehcmodule/include/libwbfs_os.h
Normal file
30
ehcmodule/include/libwbfs_os.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef LIBWBFS_OS_H
|
||||||
|
#define LIBWBFS_OS_H
|
||||||
|
// libwbfs_os.h for ehc module env
|
||||||
|
|
||||||
|
#include "syscalls.h"
|
||||||
|
#include "ehci_types.h"
|
||||||
|
#include "ehci.h"
|
||||||
|
|
||||||
|
void *WBFS_Alloc(int size);
|
||||||
|
void WBFS_Free(void *ptr);
|
||||||
|
void my_sprint(char *cad, char *s);
|
||||||
|
|
||||||
|
#define wbfs_fatal(x) do{os_puts("wbfs panic ");os_puts(x);os_puts("\n"); while(1) ehci_msleep(100);}while(0)
|
||||||
|
#define wbfs_error(x) do{os_puts("wbfs error ");os_puts(x);;os_puts("\n");}while(0)
|
||||||
|
#define wbfs_malloc(x) WBFS_Alloc(x)
|
||||||
|
#define wbfs_free(x) WBFS_Free(x)
|
||||||
|
#define wbfs_ioalloc(x) WBFS_Alloc(x)
|
||||||
|
#define wbfs_iofree(x) WBFS_Free(x)
|
||||||
|
#define wbfs_ntohl(x) (x)
|
||||||
|
#define wbfs_htonl(x) (x)
|
||||||
|
#define wbfs_ntohs(x) (x)
|
||||||
|
#define wbfs_htons(x) (x)
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#define wbfs_memcmp(x,y,z) memcmp(x,y,z)
|
||||||
|
#define wbfs_memcpy(x,y,z) memcpy(x,y,z)
|
||||||
|
#define wbfs_memset(x,y,z) memset(x,y,z)
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
9
ehcmodule/include/utils.h
Normal file
9
ehcmodule/include/utils.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#define swab32(x) ((u32)( \
|
||||||
|
(((u32)(x) & (u32)0x000000ffUL) << 24) | \
|
||||||
|
(((u32)(x) & (u32)0x0000ff00UL) << 8) | \
|
||||||
|
(((u32)(x) & (u32)0x00ff0000UL) >> 8) | \
|
||||||
|
(((u32)(x) & (u32)0xff000000UL) >> 24)))
|
||||||
|
#define swab16(x) ((u16)( \
|
||||||
|
(((u16)(x) & (u16)0x00ffU) << 8) | \
|
||||||
|
(((u16)(x) & (u16)0xff00U) >> 8)))
|
||||||
|
|
8
ehcmodule/m.bat
Normal file
8
ehcmodule/m.bat
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
make
|
||||||
|
if not %errorlevel% == 0 goto end
|
||||||
|
@echo off
|
||||||
|
cd bin
|
||||||
|
call convert.bat
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
:end
|
50
ehcmodule/scripts/link.ld
Normal file
50
ehcmodule/scripts/link.ld
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
OUTPUT_FORMAT("elf32-bigarm", "elf32-bigarm", "elf32-littlearm")
|
||||||
|
OUTPUT_ARCH(arm)
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Change exe start and ram start as needed for the custom IOS module.
|
||||||
|
Current settings are for the EHC module from IOS 31. actually this is free space in this IOS
|
||||||
|
*/
|
||||||
|
|
||||||
|
MEMORY {
|
||||||
|
ios_info_table : ORIGIN = 0x0, LENGTH = 0x4000
|
||||||
|
exe(rwx) : ORIGIN = 0x13700000, LENGTH = 0x6000
|
||||||
|
ram(rw) : ORIGIN = 0x13706000, LENGTH = 0x2A000 /* END 0x13730000 */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
__exe_start_virt__ = 0x13700000;
|
||||||
|
__exe_start_phys__ = 0x13700000;
|
||||||
|
__ram_start_virt__ = 0x13706000;
|
||||||
|
__ram_start_phys__ = 0x13706000;
|
||||||
|
__ios_info_table_start = 0x0;
|
||||||
|
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } .debug_info 0 : { *(.debug_info) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } .note.arm.ident 0 : { KEEP (*(.note.arm.ident)) }
|
||||||
|
.ios_info_table __ios_info_table_start : { . = .; KEEP (*(.ios_info_table)) } > ios_info_table
|
||||||
|
.init __exe_start_virt__ : AT (__exe_start_phys__) { . = .; KEEP (*(.init)) } > exe
|
||||||
|
.text ALIGN (0x20) : {
|
||||||
|
*(.text*)
|
||||||
|
*(.gnu.warning)
|
||||||
|
*(.gnu.linkonce.t.*)
|
||||||
|
*(.init)
|
||||||
|
*(.glue_7)
|
||||||
|
*(.glue_7t) } > exe
|
||||||
|
.data __ram_start_virt__ : AT (__ram_start_phys__) { KEEP( *(.ios_data) ) *(.data*) *(.data1) *(.gnu.linkonce.d.*) . = ALIGN (4); __CTOR_LIST__ = ABSOLUTE (.); KEEP (*(SORT (.ctors*))) __CTOR_END__ = ABSOLUTE (.); __DTOR_LIST__ = ABSOLUTE (.); KEEP (*(SORT (.dtors*))) __DTOR_END__ = ABSOLUTE (.); *(.dynamic) *(.sdata*) *(.gnu.linkonce.s.*) . = ALIGN (4); *(.2ram.*) } > ram
|
||||||
|
.fini : { . = .; *(.fini) } > ram
|
||||||
|
.rodata ALIGN (0x4) : {
|
||||||
|
. = .;
|
||||||
|
*(.rodata*)
|
||||||
|
*(.gnu.linkonce.r.*) } > ram
|
||||||
|
.rodata1 ALIGN (0x4) : { . = .; *(.rodata1) } > ram
|
||||||
|
.fixup ALIGN (0x4) : { . = .; *(.fixup) } > ram
|
||||||
|
.gcc_except_table ALIGN (0x4) : { . = .; *(.gcc_except_table) } > ram
|
||||||
|
.got ALIGN (0x4) : { *(.got.plt) *(.got) } > ram
|
||||||
|
.bss ALIGN (0x20) : { *(.scommon) *(.dynsbss) *(.sbss*) *(.gnu.linkonce.sb.*) *(.dynbss) *(.bss*) *(.gnu.linkonce.b.*) *(COMMON) KEEP( *(.ios_bss) ) } > ram
|
||||||
|
. = ALIGN(4);
|
||||||
|
}
|
2
ehcmodule/scripts/nostart.specs
Normal file
2
ehcmodule/scripts/nostart.specs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*startfile:
|
||||||
|
crti%O%s crtbegin%O%s
|
249
ehcmodule/source/crt0.s
Normal file
249
ehcmodule/source/crt0.s
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
Custom IOS module for Wii.
|
||||||
|
Copyright (C) 2008 neimod.
|
||||||
|
|
||||||
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section ".init"
|
||||||
|
.global _start
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.arm
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* crt0.s - IOS module startup code
|
||||||
|
*
|
||||||
|
*******************************************************************************
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* v1.0 - 26 July 2008 - initial release by neimod
|
||||||
|
* v1.1 - 5 September 2008 - prepared for public release
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
.EQU ios_thread_arg, 4
|
||||||
|
.EQU ios_thread_priority, 0x78 //0x48
|
||||||
|
.EQU ios_thread_stacksize, 0x3000
|
||||||
|
|
||||||
|
|
||||||
|
_start:
|
||||||
|
|
||||||
|
/* Execute main program */
|
||||||
|
mov r0, #0 @ int argc
|
||||||
|
mov r1, #0 @ char *argv[]
|
||||||
|
ldr r3, =main
|
||||||
|
bx r3
|
||||||
|
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.code 32
|
||||||
|
.global direct_syscall
|
||||||
|
direct_syscall:
|
||||||
|
ldr r12, =syscall_base
|
||||||
|
ldr r12, [r12]
|
||||||
|
nop
|
||||||
|
ldr r12, [r12,r11,lsl#2]
|
||||||
|
nop
|
||||||
|
bx r12
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.code 32
|
||||||
|
.global direct_os_sync_before_read
|
||||||
|
direct_os_sync_before_read:
|
||||||
|
|
||||||
|
|
||||||
|
mov r11, #0x3f
|
||||||
|
b direct_syscall
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.code 32
|
||||||
|
.global direct_os_sync_after_write
|
||||||
|
direct_os_sync_after_write:
|
||||||
|
|
||||||
|
|
||||||
|
mov r11, #0x40
|
||||||
|
b direct_syscall
|
||||||
|
|
||||||
|
.global ic_invalidate
|
||||||
|
ic_invalidate:
|
||||||
|
mov r0, #0
|
||||||
|
mcr p15, 0, r0, c7, c5, 0
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
// bypass to interrupt vector
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.code 32
|
||||||
|
|
||||||
|
.global interrupt_vector
|
||||||
|
interrupt_vector:
|
||||||
|
tst r8, #0x10
|
||||||
|
beq int_cont1
|
||||||
|
|
||||||
|
bic r8, r8, #0x10 // disable next EHCI treatment
|
||||||
|
|
||||||
|
mov r2, #0x10
|
||||||
|
str r2, [r7]
|
||||||
|
nop
|
||||||
|
|
||||||
|
mov r2, sp
|
||||||
|
nop
|
||||||
|
ldr sp, =_interrupt_stack
|
||||||
|
nop
|
||||||
|
|
||||||
|
stmfd sp!, {r1-r12,lr}
|
||||||
|
nop
|
||||||
|
|
||||||
|
bl _ehci_vector_
|
||||||
|
|
||||||
|
ldmfd sp!, {r1-r12,lr}
|
||||||
|
nop
|
||||||
|
mov sp, r2
|
||||||
|
|
||||||
|
tst r0, #0x1
|
||||||
|
beq int_cont1
|
||||||
|
|
||||||
|
nop
|
||||||
|
mov r0,#4
|
||||||
|
bl int_send_device_message
|
||||||
|
|
||||||
|
|
||||||
|
int_cont1:
|
||||||
|
tst r8, #0x1
|
||||||
|
beq patch2_timer_cont
|
||||||
|
// int timer
|
||||||
|
.global patch1_timer
|
||||||
|
patch1_timer:
|
||||||
|
ldr pc, =0xFFFF1E80
|
||||||
|
nop
|
||||||
|
.global patch2_timer_cont
|
||||||
|
patch2_timer_cont:
|
||||||
|
ldr pc, =0xFFFF1E9C
|
||||||
|
nop
|
||||||
|
|
||||||
|
.global int_send_device_message
|
||||||
|
int_send_device_message:
|
||||||
|
ldr pc, =0xFFFF1D44
|
||||||
|
nop
|
||||||
|
|
||||||
|
_ehci_vector_:
|
||||||
|
|
||||||
|
ldr r2,=ehci_vector
|
||||||
|
bx r2
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.code 32
|
||||||
|
.global read_access_perm
|
||||||
|
read_access_perm:
|
||||||
|
mrc p15, 0, r0,c3,c0
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.code 32
|
||||||
|
.global write_access_perm
|
||||||
|
write_access_perm:
|
||||||
|
mcr p15, 0, r0,c3,c0
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* DRIVER CONFIGURATION AREA
|
||||||
|
*
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
.string "EHC_CFG"
|
||||||
|
.long 0x12340001
|
||||||
|
.global use_usb_port1
|
||||||
|
use_usb_port1:
|
||||||
|
.byte 0x0
|
||||||
|
|
||||||
|
.global use_reset_bulk
|
||||||
|
use_reset_bulk:
|
||||||
|
.byte 0x0
|
||||||
|
|
||||||
|
/* force_flags 1 ->force GetMaxLun, 2-> force SetConfiguration */
|
||||||
|
.global force_flags
|
||||||
|
force_flags:
|
||||||
|
.byte 0x0
|
||||||
|
|
||||||
|
.global use_alternative_timeout
|
||||||
|
use_alternative_timeout:
|
||||||
|
.byte 0x0
|
||||||
|
|
||||||
|
.align
|
||||||
|
.pool
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* IOS data section
|
||||||
|
*
|
||||||
|
* Basically, this is required for the program header not to be messed up
|
||||||
|
* The program header will only be generated correctly if there is "something"
|
||||||
|
* in the ram segment, this makes sure of that by placing a silly string there.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
.section ".ios_data" ,"aw",%progbits
|
||||||
|
.ascii "IOS module"
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* IOS bss section
|
||||||
|
*
|
||||||
|
* This contains the module's thread stack
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
.section ".ios_bss", "a", %nobits
|
||||||
|
|
||||||
|
.global ios_thread_stack_start
|
||||||
|
ios_thread_stack_start:
|
||||||
|
.space ios_thread_stacksize
|
||||||
|
.global ios_thread_stack /* stack decrements from high address.. */
|
||||||
|
ios_thread_stack:
|
||||||
|
.space 0x200
|
||||||
|
_interrupt_stack:
|
||||||
|
|
||||||
|
.section ".ios_info_table","ax",%progbits
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* IOS info table section
|
||||||
|
*
|
||||||
|
* This contains the module's loader information
|
||||||
|
* The stripios tool will find this, and package it nicely for the IOS system
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
.global ios_info_table
|
||||||
|
ios_info_table:
|
||||||
|
.long 0x0
|
||||||
|
.long 0x28 @ numentries * 0x28
|
||||||
|
.long 0x6
|
||||||
|
.long 0xB
|
||||||
|
.long ios_thread_arg @ passed to thread entry func, maybe module id
|
||||||
|
.long 0x9
|
||||||
|
.long _start
|
||||||
|
.long 0x7D
|
||||||
|
.long ios_thread_priority
|
||||||
|
.long 0x7E
|
||||||
|
.long ios_thread_stacksize
|
||||||
|
.long 0x7F
|
||||||
|
.long ios_thread_stack
|
||||||
|
|
||||||
|
|
||||||
|
.pool
|
||||||
|
.end
|
865
ehcmodule/source/ehc_loop.c
Normal file
865
ehcmodule/source/ehc_loop.c
Normal file
@ -0,0 +1,865 @@
|
|||||||
|
/*
|
||||||
|
Custom IOS module for Wii.
|
||||||
|
OH0 message loop
|
||||||
|
Copyright (C) 2009 kwiirk.
|
||||||
|
Copyright (C) 2008 neimod.
|
||||||
|
|
||||||
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* oh0_loop.c - IOS module main code
|
||||||
|
* even if we are "ehc" driver, we still pretend to be "oh0"
|
||||||
|
* and implement "standard" ios oh0 usb api
|
||||||
|
*
|
||||||
|
*******************************************************************************
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "syscalls.h"
|
||||||
|
#include "ehci_types.h"
|
||||||
|
#include "ehci.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "libwbfs.h"
|
||||||
|
#include "ehci_interrupt.h"
|
||||||
|
|
||||||
|
#undef ehci_writel
|
||||||
|
#define ehci_writel(v,a) do{*((volatile u32*)(a))=(v);}while(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ehci_usleep(int usec);
|
||||||
|
void ehci_msleep(int msec);
|
||||||
|
|
||||||
|
int ehci_release_externals_usb_ports(void);
|
||||||
|
|
||||||
|
void off_callback_hand(u32 flags);
|
||||||
|
|
||||||
|
int disable_ehc=0;
|
||||||
|
|
||||||
|
#undef NULL
|
||||||
|
#define NULL ((void *)0)
|
||||||
|
#define IOS_OPEN 0x01
|
||||||
|
#define IOS_CLOSE 0x02
|
||||||
|
#define IOS_IOCTL 0x06
|
||||||
|
#define IOS_IOCTLV 0x07
|
||||||
|
|
||||||
|
#define USB_IOCTL_CTRLMSG 0
|
||||||
|
#define USB_IOCTL_BLKMSG 1
|
||||||
|
#define USB_IOCTL_INTRMSG 2
|
||||||
|
#define USB_IOCTL_SUSPENDDEV 5
|
||||||
|
#define USB_IOCTL_RESUMEDEV 6
|
||||||
|
#define USB_IOCTL_GETDEVLIST 12
|
||||||
|
#define USB_IOCTL_DEVREMOVALHOOK 26
|
||||||
|
#define USB_IOCTL_DEVINSERTHOOK 27
|
||||||
|
|
||||||
|
#define UMS_BASE (('U'<<24)|('M'<<16)|('S'<<8))
|
||||||
|
#define USB_IOCTL_UMS_INIT (UMS_BASE+0x1)
|
||||||
|
#define USB_IOCTL_UMS_GET_CAPACITY (UMS_BASE+0x2)
|
||||||
|
#define USB_IOCTL_UMS_READ_SECTORS (UMS_BASE+0x3)
|
||||||
|
#define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4)
|
||||||
|
|
||||||
|
#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5)
|
||||||
|
|
||||||
|
#define USB_IOCTL_UMS_SET_VERBOSE (UMS_BASE+0x6)
|
||||||
|
|
||||||
|
#define USB_IOCTL_UMS_UMOUNT (UMS_BASE+0x10)
|
||||||
|
#define USB_IOCTL_UMS_WATCHDOG (UMS_BASE+0x80)
|
||||||
|
|
||||||
|
#define USB_IOCTL_UMS_TESTMODE (UMS_BASE+0x81)
|
||||||
|
|
||||||
|
#define USB_IOCTL_UMS_OFF (UMS_BASE+0x82)
|
||||||
|
#define USB_IOCTL_SET_PORT (UMS_BASE+0x83)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define WBFS_BASE (('W'<<24)|('F'<<16)|('S'<<8))
|
||||||
|
#define USB_IOCTL_WBFS_OPEN_DISC (WBFS_BASE+0x1)
|
||||||
|
#define USB_IOCTL_WBFS_READ_DISC (WBFS_BASE+0x2)
|
||||||
|
#define USB_IOCTL_WBFS_READ_DIRECT_DISC (WBFS_BASE+0x3)
|
||||||
|
#define USB_IOCTL_WBFS_STS_DISC (WBFS_BASE+0x4)
|
||||||
|
|
||||||
|
//#define USB_IOCTL_WBFS_SPEED_LIMIT (WBFS_BASE+0x80)
|
||||||
|
|
||||||
|
void USBStorage_Umount(void);
|
||||||
|
|
||||||
|
//#define DEVICE "/dev/usb/ehc"
|
||||||
|
#define DEVICE "/dev/usb123"
|
||||||
|
|
||||||
|
int verbose = 0;
|
||||||
|
#define ioctlv_u8(a) (*((u8*)(a).data))
|
||||||
|
#define ioctlv_u16(a) (*((u16*)(a).data))
|
||||||
|
#define ioctlv_u32(a) (*((u32*)(a).data))
|
||||||
|
#define ioctlv_len(a) (a).len
|
||||||
|
#define ioctlv_voidp(a) (a).data
|
||||||
|
|
||||||
|
wbfs_disc_t * wbfs_init_with_partition(u8*discid, int partition);
|
||||||
|
|
||||||
|
extern char use_usb_port1;
|
||||||
|
|
||||||
|
|
||||||
|
int USBStorage_DVD_Test(void);
|
||||||
|
|
||||||
|
#define WATCHDOG_TIMER 1000*1000*10
|
||||||
|
|
||||||
|
|
||||||
|
int test_mode=0;
|
||||||
|
|
||||||
|
char *parse_hex(char *base,int *val)
|
||||||
|
{
|
||||||
|
int v = 0,done=0;
|
||||||
|
char *ptr = base,c;
|
||||||
|
while(!done)
|
||||||
|
{
|
||||||
|
c = *ptr++;
|
||||||
|
if(c >= '0' && c <= '9')
|
||||||
|
v = v << 4 | (c-'0');
|
||||||
|
else if(c >= 'a' && c <= 'f')
|
||||||
|
v = v << 4 | (10+c-'a');
|
||||||
|
else if(c >= 'A' && c <= 'F')
|
||||||
|
v = v << 4 | (10+c-'A');
|
||||||
|
else
|
||||||
|
done = 1;
|
||||||
|
}
|
||||||
|
if(ptr==base+1)//only incremented once
|
||||||
|
return 0; //we did not found any hex numbers
|
||||||
|
*val = v;
|
||||||
|
return ptr-1;
|
||||||
|
}
|
||||||
|
int parse_and_open_device(char *devname,int fd)
|
||||||
|
{
|
||||||
|
char *ptr = devname;
|
||||||
|
int vid,pid;
|
||||||
|
if (! (ptr = parse_hex(ptr,&vid)))
|
||||||
|
return -6;
|
||||||
|
if ( *ptr != '/' )
|
||||||
|
return -6;
|
||||||
|
ptr++;// skip /
|
||||||
|
if (! (ptr = parse_hex(ptr,&pid)))
|
||||||
|
return -6;
|
||||||
|
if ( *ptr != '\0' )
|
||||||
|
return -6;
|
||||||
|
return ehci_open_device(vid,pid,fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int DVD_speed_limit=0; // ingame it can fix x6 speed
|
||||||
|
|
||||||
|
int watchdog_enable=1;
|
||||||
|
|
||||||
|
// special ingame
|
||||||
|
int wbfs_disc_read2(wbfs_disc_t*d,u32 offset, u8 *data, u32 len);
|
||||||
|
|
||||||
|
// heap space for WBFS and queue
|
||||||
|
|
||||||
|
extern int heaphandle;
|
||||||
|
|
||||||
|
void msleep(int msec);
|
||||||
|
|
||||||
|
u8 mem_sector[4096] __attribute__ ((aligned (32)));
|
||||||
|
|
||||||
|
void *WBFS_Alloc(int size)
|
||||||
|
{
|
||||||
|
void * ret = 0;
|
||||||
|
// ret= os_heap_alloc(heaphandle, size);
|
||||||
|
ret= os_heap_alloc_aligned(heaphandle, size, 32);
|
||||||
|
if(ret==0)
|
||||||
|
{debug_printf("WBFS not enough memory! need %d\n",size);
|
||||||
|
os_puts("WBFS not enough memory!\n");
|
||||||
|
|
||||||
|
while(1) {swi_mload_led_on();ehci_msleep(200);swi_mload_led_off();ehci_msleep(200);}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WBFS_Free(void *ptr)
|
||||||
|
{
|
||||||
|
return os_heap_free(heaphandle, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern u8 *disc_buff;
|
||||||
|
|
||||||
|
u32 last_disc_lba=0;
|
||||||
|
u32 current_disc_lba=0xffffffff;
|
||||||
|
|
||||||
|
|
||||||
|
void wbfs_perform_disc(void);
|
||||||
|
|
||||||
|
// CISO mem area
|
||||||
|
int ciso_lba=-1;
|
||||||
|
int ciso_size=0;
|
||||||
|
u32 table_lba[2048];
|
||||||
|
u8 mem_index[2048] __attribute__ ((aligned (32)));
|
||||||
|
|
||||||
|
|
||||||
|
// offset -> disc_offset in words
|
||||||
|
// data -> buffer
|
||||||
|
// len -> len to read in bytes
|
||||||
|
|
||||||
|
int WBFS_direct_disc_read(u32 offset, u8 *data, u32 len)
|
||||||
|
{
|
||||||
|
int r=true;
|
||||||
|
u32 lba;
|
||||||
|
u32 len2=len;
|
||||||
|
u8* data2=data;
|
||||||
|
u32 sec_size;
|
||||||
|
int l;
|
||||||
|
u8 *buff;
|
||||||
|
|
||||||
|
os_sync_after_write(data2, len2);
|
||||||
|
|
||||||
|
if(!disc_buff) return 0x8000;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
last_disc_lba= USBStorage_Get_Capacity(&sec_size);
|
||||||
|
|
||||||
|
if(last_disc_lba==0 || sec_size!=2048)
|
||||||
|
{
|
||||||
|
current_disc_lba=0xffffffff;
|
||||||
|
return 0x8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ciso_lba>=0 && ciso_lba!=0x7fffffff && current_disc_lba==0xffffffff)
|
||||||
|
{
|
||||||
|
u32 lba_glob;
|
||||||
|
|
||||||
|
current_disc_lba=0xffffffff;
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
lba_glob=ciso_lba+16;
|
||||||
|
|
||||||
|
buff=(u8 *) (((u32)disc_buff+31) & ~31); // 32 bytes aligment
|
||||||
|
r=USBStorage_Read_Sectors(ciso_lba, 16, buff); // read 16 cached sectors
|
||||||
|
if(!r) return 0x8000;
|
||||||
|
|
||||||
|
if((buff[0]=='C' && buff[1]=='I' && buff[2]=='S' && buff[3]=='O')) ciso_lba=0x7fffffff;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(ciso_lba!=0) {ciso_lba=0;continue;}
|
||||||
|
ciso_lba=-1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ciso_size=(((u32)buff[4])+(((u32)buff[5])<<8)+(((u32)buff[6])<<16)+(((u32)buff[7])<<24))/2048;
|
||||||
|
|
||||||
|
memset(mem_index,0,2048);
|
||||||
|
|
||||||
|
if(ciso_lba==0x7fffffff)
|
||||||
|
|
||||||
|
for(l=0;l<16384;l++)
|
||||||
|
{
|
||||||
|
if((l & 7)==0) table_lba[l>>3]=lba_glob;
|
||||||
|
|
||||||
|
if(buff[8+l])
|
||||||
|
{
|
||||||
|
mem_index[l>>3]|=1<<(l & 7);
|
||||||
|
lba_glob+=ciso_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
buff=(u8 *) (((u32)disc_buff+31) & ~31); // 32 bytes aligment
|
||||||
|
|
||||||
|
while(len>0)
|
||||||
|
{
|
||||||
|
lba=offset>>9; // offset to LBA (sector have 512 words)
|
||||||
|
|
||||||
|
if((lba & ~15)!=current_disc_lba)
|
||||||
|
{
|
||||||
|
u32 read_lba;
|
||||||
|
|
||||||
|
current_disc_lba=(lba & ~15);
|
||||||
|
|
||||||
|
read_lba=current_disc_lba;
|
||||||
|
|
||||||
|
if(ciso_lba==0x7fffffff)
|
||||||
|
{
|
||||||
|
u32 temp=current_disc_lba/ciso_size;
|
||||||
|
|
||||||
|
read_lba=table_lba[temp>>3];
|
||||||
|
|
||||||
|
for(l=0;l<(temp & 7);l++) if((mem_index[temp>>3]>>l) & 1) read_lba+=ciso_size;
|
||||||
|
|
||||||
|
read_lba+=current_disc_lba & (ciso_size-1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
l=(last_disc_lba-read_lba/*current_disc_lba*/);if(l>16) l=16;
|
||||||
|
|
||||||
|
|
||||||
|
if(l<16) memset(buff,0,0x8000);
|
||||||
|
if(l>0)
|
||||||
|
{
|
||||||
|
r=USBStorage_Read_Sectors(/*current_disc_lba*/read_lba, l, buff); // read 16 cached sectors
|
||||||
|
if(!r) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
l=0x8000-((offset & 8191)<<2); // get max size in the cache relative to offset
|
||||||
|
if(l>len) l=len;
|
||||||
|
|
||||||
|
memcpy(data, &buff[((offset & 8191)<<2)], l);
|
||||||
|
os_sync_after_write(data, l);
|
||||||
|
|
||||||
|
data+=l;
|
||||||
|
len-=l;
|
||||||
|
offset+=l>>2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!r) return 0x8000;
|
||||||
|
os_sync_before_read(data2, len2);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern int unplug_device;
|
||||||
|
|
||||||
|
int unplug_procedure(void);
|
||||||
|
|
||||||
|
extern int is_watchdog_read_sector;
|
||||||
|
|
||||||
|
extern u32 n_sec,sec_size;
|
||||||
|
|
||||||
|
int last_sector=0;
|
||||||
|
|
||||||
|
|
||||||
|
void direct_os_sync_before_read(void* ptr, int size);
|
||||||
|
void direct_os_sync_after_write(void* ptr, int size);
|
||||||
|
u32 read_access_perm(void);
|
||||||
|
void write_access_perm(u32 flags);
|
||||||
|
|
||||||
|
/******************************************************************************************************************************************************/
|
||||||
|
// dev/di ioctl os_message_queue_receive
|
||||||
|
/******************************************************************************************************************************************************/
|
||||||
|
|
||||||
|
int swi_di_queue(u32 cmd, ipcmessage *message)
|
||||||
|
{
|
||||||
|
u32 perm;
|
||||||
|
|
||||||
|
perm=read_access_perm();
|
||||||
|
write_access_perm(0xffffffff);
|
||||||
|
message->ioctl.command=cmd;
|
||||||
|
*((u32 *) message->ioctl.buffer_in)=cmd<<24;
|
||||||
|
direct_os_sync_after_write(&message->ioctl.command,4);
|
||||||
|
direct_os_sync_after_write(message->ioctl.buffer_in,4);
|
||||||
|
write_access_perm(perm);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int my_di_os_message_queue_receive(int queuehandle, ipcmessage ** message,int flag)
|
||||||
|
{
|
||||||
|
int ret,ret2;
|
||||||
|
|
||||||
|
|
||||||
|
ret= os_message_queue_receive(queuehandle, (void*) message, flag);
|
||||||
|
|
||||||
|
|
||||||
|
if(ret==0 && message && *message)
|
||||||
|
{
|
||||||
|
|
||||||
|
if((*message)->command==IOS_IOCTL)
|
||||||
|
{
|
||||||
|
switch((*message)->ioctl.command)
|
||||||
|
{
|
||||||
|
case 0x7a:
|
||||||
|
ret2=swi_mload_call_func((void *) swi_di_queue, (void *) 0x15, (void *) (*message));
|
||||||
|
break;
|
||||||
|
case 0x88:
|
||||||
|
ret2=swi_mload_call_func((void *) swi_di_queue, (void *) 0x14, (void *) (*message));
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************************************************************************************/
|
||||||
|
// ehcmodule swi service
|
||||||
|
/******************************************************************************************************************************************************/
|
||||||
|
void release_wbfs_mem(void);
|
||||||
|
|
||||||
|
int swi_ehcmodule(u32 cmd, u32 param1, u32 param2, u32 param3)
|
||||||
|
{
|
||||||
|
s32 ret=-666;
|
||||||
|
|
||||||
|
switch(cmd)
|
||||||
|
{
|
||||||
|
case 0: // get mem alloc handle (139264 bytes heap)
|
||||||
|
ret=heaphandle;
|
||||||
|
break;
|
||||||
|
case 1: // obtain release_wbfs_mem() function to be sure you have free memory
|
||||||
|
ret=(int) release_wbfs_mem;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ret=0;disable_ehc=1; // disable ehcmodule device for direct access operations
|
||||||
|
break;
|
||||||
|
case 16: // get USBStorage_Read_Sectors() for direct operations (remember you disable_ehc must be 1)
|
||||||
|
ret= (int) USBStorage_Read_Sectors;
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
ret= (int) USBStorage_Write_Sectors;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ehc_loop(void)
|
||||||
|
{
|
||||||
|
ipcmessage* message;
|
||||||
|
int timer2_id=-1;
|
||||||
|
static bool first_read=true;
|
||||||
|
char port;
|
||||||
|
|
||||||
|
extern int ums_init_done;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int must_read_sectors=0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void* queuespace = os_heap_alloc(heaphandle, 0x80);
|
||||||
|
|
||||||
|
|
||||||
|
int queuehandle = os_message_queue_create(queuespace, 32);
|
||||||
|
|
||||||
|
|
||||||
|
init_thread_ehci();
|
||||||
|
|
||||||
|
os_thread_set_priority(os_get_thread_id(), /*os_thread_get_priority()-1*/0x78);
|
||||||
|
|
||||||
|
os_device_register(DEVICE, queuehandle);
|
||||||
|
timer2_id=os_create_timer(WATCHDOG_TIMER, WATCHDOG_TIMER, queuehandle, 0x0);
|
||||||
|
|
||||||
|
int ums_mode = 0;
|
||||||
|
int already_discovered = 0;
|
||||||
|
wbfs_disc_t *d = 0;
|
||||||
|
|
||||||
|
int usb_lock=0;
|
||||||
|
|
||||||
|
int watch_time_on=1;
|
||||||
|
|
||||||
|
// register SWI function (0xcd)
|
||||||
|
|
||||||
|
swi_mload_add_handler(0xcd, swi_ehcmodule);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
int result = 1;
|
||||||
|
int ack = 1;
|
||||||
|
volatile int ret;
|
||||||
|
|
||||||
|
// Wait for message to arrive
|
||||||
|
ret=os_message_queue_receive(queuehandle, (void*)&message, 0);
|
||||||
|
if(ret) continue;
|
||||||
|
|
||||||
|
|
||||||
|
// timer message WATCHDOG
|
||||||
|
//if((int) message==0x555) continue;
|
||||||
|
|
||||||
|
if(watch_time_on)
|
||||||
|
os_stop_timer(timer2_id); // stops watchdog timer
|
||||||
|
watch_time_on=0;
|
||||||
|
|
||||||
|
is_watchdog_read_sector=0;
|
||||||
|
|
||||||
|
if((int) message==0x0)
|
||||||
|
{
|
||||||
|
if(test_mode && !disable_ehc)
|
||||||
|
watchdog_enable=0; // test mode blocks watchdog
|
||||||
|
|
||||||
|
if(must_read_sectors && watchdog_enable && !disable_ehc)
|
||||||
|
{
|
||||||
|
int n,r;
|
||||||
|
|
||||||
|
if(unplug_device)
|
||||||
|
{
|
||||||
|
for(n=0;n<3;n++)
|
||||||
|
if(!unplug_procedure()) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(unplug_device==0)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(sec_size!=0 && sec_size<4096) // only support sector size minor to 2048
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
is_watchdog_read_sector=1;
|
||||||
|
|
||||||
|
r=USBStorage_Read_Sectors(last_sector, 1, mem_sector);
|
||||||
|
|
||||||
|
is_watchdog_read_sector=0;
|
||||||
|
if(r!=0 && sec_size==512)
|
||||||
|
last_sector+=0x1000000/sec_size; // steps of 16MB
|
||||||
|
if(last_sector>=n_sec) last_sector=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!disable_ehc)
|
||||||
|
{
|
||||||
|
watch_time_on=1;
|
||||||
|
os_restart_timer(timer2_id, WATCHDOG_TIMER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//print_hex_dump_bytes("msg",0, message,sizeof(*message));
|
||||||
|
switch( message->command )
|
||||||
|
{
|
||||||
|
case IOS_OPEN:
|
||||||
|
{
|
||||||
|
|
||||||
|
//debug_printf("%s try open %sfor fd %d\n",DEVICE,message->open.device,message->open.resultfd);
|
||||||
|
// Checking device name
|
||||||
|
if (0 == strcmp(message->open.device, DEVICE))
|
||||||
|
{
|
||||||
|
result = message->open.resultfd;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == strcmp(message->open.device, DEVICE"/OFF"))
|
||||||
|
{
|
||||||
|
result = message->open.resultfd;
|
||||||
|
disable_ehc=1;
|
||||||
|
|
||||||
|
must_read_sectors=0;
|
||||||
|
watchdog_enable=0;
|
||||||
|
|
||||||
|
ehci_int_passive_callback(off_callback_hand);
|
||||||
|
ehci_writel (STS_PCD, &ehci->regs->intr_enable);
|
||||||
|
ehci_release_externals_usb_ports();
|
||||||
|
|
||||||
|
//swi_mload_led_on();
|
||||||
|
|
||||||
|
}
|
||||||
|
/*else if (!ums_mode && 0 == memcmp(message->open.device, DEVICE"/", sizeof(DEVICE)) && !disable_ehc)
|
||||||
|
result = parse_and_open_device(message->open.device+sizeof(DEVICE),message->open.resultfd);
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
result = -6;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOS_CLOSE:
|
||||||
|
{
|
||||||
|
|
||||||
|
//debug_printf("close fd %d\n",message->fd);
|
||||||
|
//USBStorage_Umount();
|
||||||
|
//ehci_release_externals_usb_ports();
|
||||||
|
|
||||||
|
if(ums_mode == message->fd)
|
||||||
|
ums_mode = 0;
|
||||||
|
else
|
||||||
|
ehci_close_devices();
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOS_IOCTL:
|
||||||
|
{
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IOS_IOCTLV:
|
||||||
|
{
|
||||||
|
ioctlv *vec = message->ioctlv.vector;
|
||||||
|
void *dev =NULL;
|
||||||
|
int i,in = message->ioctlv.num_in,io= message->ioctlv.num_io;
|
||||||
|
if( 0==(message->ioctl.command>>24) && !ums_mode)
|
||||||
|
dev = ehci_fd_to_dev(message->fd);
|
||||||
|
os_sync_before_read( vec, (in+io)*sizeof(ioctlv));
|
||||||
|
for(i=0;i<in+io;i++){
|
||||||
|
os_sync_before_read( vec[i].data, vec[i].len);
|
||||||
|
//print_hex_dump_bytes("vec",0, vec[i].data,vec[i].len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(disable_ehc)
|
||||||
|
{
|
||||||
|
result=-1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
switch( message->ioctl.command )
|
||||||
|
{
|
||||||
|
case USB_IOCTL_CTRLMSG:
|
||||||
|
//debug_printf("ctrl message%x\n",dev);
|
||||||
|
if(!dev)result= -6;
|
||||||
|
else
|
||||||
|
result = ehci_control_message(dev,ioctlv_u8(vec[0]),ioctlv_u8(vec[1]),
|
||||||
|
swab16(ioctlv_u16(vec[2])),swab16(ioctlv_u16(vec[3])),
|
||||||
|
swab16(ioctlv_u16(vec[4])),ioctlv_voidp(vec[6]));
|
||||||
|
break;
|
||||||
|
case USB_IOCTL_BLKMSG:
|
||||||
|
//debug_printf("bulk message\n");
|
||||||
|
if(!dev)result= -6;
|
||||||
|
else
|
||||||
|
result = ehci_bulk_message(dev,ioctlv_u8(vec[0]),ioctlv_u16(vec[1]),
|
||||||
|
ioctlv_voidp(vec[2]));
|
||||||
|
break;
|
||||||
|
case USB_IOCTL_INTRMSG:
|
||||||
|
debug_printf("intr message\n");
|
||||||
|
case USB_IOCTL_SUSPENDDEV:
|
||||||
|
case USB_IOCTL_RESUMEDEV:
|
||||||
|
debug_printf("or resume/suspend message\n");
|
||||||
|
result = 0;//-1;// not supported
|
||||||
|
break;
|
||||||
|
case USB_IOCTL_GETDEVLIST:
|
||||||
|
debug_printf("get dev list\n");
|
||||||
|
if(dev)result= -6;
|
||||||
|
else
|
||||||
|
result = ehci_get_device_list(ioctlv_u8(vec[0]),ioctlv_u8(vec[1]),
|
||||||
|
ioctlv_voidp(vec[2]),ioctlv_voidp(vec[3]));
|
||||||
|
break;
|
||||||
|
case USB_IOCTL_DEVREMOVALHOOK:
|
||||||
|
case USB_IOCTL_DEVINSERTHOOK:
|
||||||
|
debug_printf("removal/insert hook\n");
|
||||||
|
ack = 0; // dont reply to those, as we dont detect anything
|
||||||
|
break;
|
||||||
|
case USB_IOCTL_UMS_INIT:
|
||||||
|
must_read_sectors=0;
|
||||||
|
|
||||||
|
if(!already_discovered )
|
||||||
|
ehci_discover();
|
||||||
|
already_discovered=1;
|
||||||
|
|
||||||
|
result = USBStorage_Init();
|
||||||
|
|
||||||
|
|
||||||
|
//result=-os_thread_get_priority();
|
||||||
|
if(result>=0) {must_read_sectors=1;watchdog_enable=1;}
|
||||||
|
ums_mode = message->fd;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case USB_IOCTL_UMS_UMOUNT:
|
||||||
|
must_read_sectors=0;
|
||||||
|
watchdog_enable=0;
|
||||||
|
// USBStorage_Umount();
|
||||||
|
result =0;
|
||||||
|
break;
|
||||||
|
case USB_IOCTL_UMS_TESTMODE:
|
||||||
|
test_mode=ioctlv_u32(vec[0]);
|
||||||
|
result =0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case USB_IOCTL_SET_PORT:
|
||||||
|
result =0;
|
||||||
|
port=ioctlv_u32(vec[0]);
|
||||||
|
if(use_usb_port1!=port)
|
||||||
|
{
|
||||||
|
if(ums_init_done)
|
||||||
|
{
|
||||||
|
USBStorage_Umount();
|
||||||
|
ehci_close_devices();
|
||||||
|
ehci_release_externals_usb_ports();
|
||||||
|
use_usb_port1=port;
|
||||||
|
ehci_discover();
|
||||||
|
result = USBStorage_Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
use_usb_port1=port;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case USB_IOCTL_UMS_OFF:
|
||||||
|
{
|
||||||
|
|
||||||
|
disable_ehc=1;
|
||||||
|
|
||||||
|
must_read_sectors=0;
|
||||||
|
watchdog_enable=0;
|
||||||
|
|
||||||
|
ehci_int_passive_callback(off_callback_hand);
|
||||||
|
ehci_writel (STS_PCD, &ehci->regs->intr_enable);
|
||||||
|
ehci_release_externals_usb_ports();
|
||||||
|
|
||||||
|
result =0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case USB_IOCTL_UMS_GET_CAPACITY:
|
||||||
|
n_sec = USBStorage_Get_Capacity(&sec_size);
|
||||||
|
if(ioctlv_voidp(vec[0]))
|
||||||
|
{
|
||||||
|
*((u32 *) ioctlv_voidp(vec[0]))= sec_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
result =n_sec ;
|
||||||
|
break;
|
||||||
|
case USB_IOCTL_UMS_READ_SECTORS:
|
||||||
|
#ifdef VIGILANTE
|
||||||
|
enable_button=1;
|
||||||
|
#endif
|
||||||
|
result = USBStorage_Read_Sectors(ioctlv_u32(vec[0]),ioctlv_u32(vec[1]), ioctlv_voidp(vec[2]));
|
||||||
|
if(first_read)
|
||||||
|
{
|
||||||
|
void s_printf(char *format,...);
|
||||||
|
//#define s_printf(a...)
|
||||||
|
first_read=false;
|
||||||
|
|
||||||
|
if(result>0)
|
||||||
|
s_printf("first read sector (%i) OK\n",ioctlv_u32(vec[0]));
|
||||||
|
else
|
||||||
|
s_printf("first read sector (%i) ERROR\n",ioctlv_u32(vec[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case USB_IOCTL_UMS_WRITE_SECTORS:
|
||||||
|
#ifdef VIGILANTE
|
||||||
|
enable_button=1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
result = USBStorage_Write_Sectors(ioctlv_u32(vec[0]),ioctlv_u32(vec[1]), ioctlv_voidp(vec[2]));
|
||||||
|
break;
|
||||||
|
case USB_IOCTL_UMS_READ_STRESS:
|
||||||
|
// result = USBStorage_Read_Stress(ioctlv_u32(vec[0]),ioctlv_u32(vec[1]), ioctlv_voidp(vec[2]));
|
||||||
|
break;
|
||||||
|
case USB_IOCTL_UMS_SET_VERBOSE:
|
||||||
|
verbose = !verbose;
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
/*case USB_IOCTL_WBFS_SPEED_LIMIT:
|
||||||
|
DVD_speed_limit=ioctlv_u32(vec[0]);
|
||||||
|
break;*/
|
||||||
|
case USB_IOCTL_UMS_WATCHDOG:
|
||||||
|
watchdog_enable=ioctlv_u32(vec[0]);
|
||||||
|
break;
|
||||||
|
case USB_IOCTL_WBFS_OPEN_DISC:
|
||||||
|
ums_mode = message->fd;
|
||||||
|
u8 *discid;
|
||||||
|
|
||||||
|
int partition=0;
|
||||||
|
#ifdef VIGILANTE
|
||||||
|
enable_button=1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
discid=ioctlv_voidp(vec[0]);
|
||||||
|
if(discid[0]=='_' && discid[1]=='D' && discid[2]=='V' && discid[3]=='D')
|
||||||
|
{
|
||||||
|
result = 0;watchdog_enable=1;
|
||||||
|
ciso_lba=0;
|
||||||
|
if(vec[1].len==4)
|
||||||
|
{
|
||||||
|
memcpy(&partition, ioctlv_voidp(vec[1]), 4);
|
||||||
|
ciso_lba=partition;
|
||||||
|
}
|
||||||
|
|
||||||
|
//ciso_lba=265;
|
||||||
|
wbfs_perform_disc();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
if(vec[1].len==4) memcpy(&partition, ioctlv_voidp(vec[1]), 4);
|
||||||
|
d = wbfs_init_with_partition(discid, partition);
|
||||||
|
if(!d)
|
||||||
|
result = -1;
|
||||||
|
else
|
||||||
|
{result = 0;watchdog_enable=1;}
|
||||||
|
}
|
||||||
|
|
||||||
|
must_read_sectors=1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case USB_IOCTL_WBFS_STS_DISC:
|
||||||
|
result=USBStorage_DVD_Test();
|
||||||
|
if(result==0) current_disc_lba=0xffffffff; // test fail
|
||||||
|
|
||||||
|
break;
|
||||||
|
case USB_IOCTL_WBFS_READ_DIRECT_DISC: // used to read USB DVD
|
||||||
|
usb_lock=1;
|
||||||
|
watchdog_enable=1;
|
||||||
|
result = WBFS_direct_disc_read(ioctlv_u32(vec[0]),ioctlv_voidp(vec[2]),ioctlv_u32(vec[1]));
|
||||||
|
usb_lock=0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case USB_IOCTL_WBFS_READ_DISC:
|
||||||
|
/*if (verbose)
|
||||||
|
debug_printf("r%x %x\n",ioctlv_u32(vec[0]),ioctlv_u32(vec[1]));
|
||||||
|
else
|
||||||
|
debug_printf("r%x %x\r",ioctlv_u32(vec[0]),ioctlv_u32(vec[1]));
|
||||||
|
*/
|
||||||
|
if(!d /*|| usb_lock*/)
|
||||||
|
result = -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
usb_lock=1;
|
||||||
|
//os_stop_timer(timer2_id);
|
||||||
|
result = wbfs_disc_read(d,ioctlv_u32(vec[0]),ioctlv_voidp(vec[2]),ioctlv_u32(vec[1]));
|
||||||
|
usb_lock=0;
|
||||||
|
if(result){
|
||||||
|
//debug_printf("wbfs failed! %d\n",result);
|
||||||
|
//result = 0x7800; // wii games shows unrecoverable error..
|
||||||
|
result = 0;//0x8000;
|
||||||
|
}
|
||||||
|
//result=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for(i=in;i<in+io;i++){
|
||||||
|
//print_hex_dump_bytes("iovec",0, vec[i].data,vec[i].len>0x20?0x20:vec[i].len);
|
||||||
|
os_sync_after_write( vec[i].data, vec[i].len);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
result = -1;
|
||||||
|
//ack = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(watchdog_enable)
|
||||||
|
{
|
||||||
|
watch_time_on=1;
|
||||||
|
os_restart_timer(timer2_id, WATCHDOG_TIMER);
|
||||||
|
}
|
||||||
|
// Acknowledge message
|
||||||
|
|
||||||
|
if (ack)
|
||||||
|
os_message_queue_ack( (void*)message, result );
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
188
ehcmodule/source/ehci_interrupt.c
Normal file
188
ehcmodule/source/ehci_interrupt.c
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
#include "ehci_interrupt.h"
|
||||||
|
#include "swi_mload.h"
|
||||||
|
|
||||||
|
#define ehci_readl(a) (*((volatile u32*)(a)))
|
||||||
|
#define ehci_writel(v,a) do{*((volatile u32*)(a))=(v);}while(0)
|
||||||
|
#define get_timer() (*(((volatile u32*)0x0D800010)))
|
||||||
|
|
||||||
|
void enable_EHCI_IRQ(void)
|
||||||
|
{
|
||||||
|
*((volatile u32 *) 0x0d0400cc)|=1<<15;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disable_EHCI_IRQ(void)
|
||||||
|
{
|
||||||
|
*((volatile u32 *) 0x0d0400cc) &=~(1<<15);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
void enable_OHCI0_IRQ(void)
|
||||||
|
{
|
||||||
|
*((volatile u32 *) 0x0d0400cc)|=1<<11;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disable_OHCI0_IRQ(void)
|
||||||
|
{
|
||||||
|
*((volatile u32 *) 0x0d0400cc) &=~(1<<11);
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_OHCI1_IRQ(void)
|
||||||
|
{
|
||||||
|
*((volatile u32 *) 0x0d0400cc)|=1<<12;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disable_OHCI1_IRQ(void)
|
||||||
|
{
|
||||||
|
*((volatile u32 *) 0x0d0400cc) &=~(1<<12);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int ehci1_queuehandle=-1;
|
||||||
|
|
||||||
|
|
||||||
|
void init_thread_ehci(void)
|
||||||
|
{
|
||||||
|
disable_EHCI_IRQ();
|
||||||
|
|
||||||
|
|
||||||
|
ehci1_queuehandle= os_message_queue_create( USB_Alloc(4*32)/*os_heap_alloc(heaphandle, 4*32)*/, 32);
|
||||||
|
|
||||||
|
os_unregister_event_handler(DEV_EHCI);
|
||||||
|
os_register_event_handler(DEV_EHCI, ehci1_queuehandle, 0); // register interrupt event handler
|
||||||
|
|
||||||
|
enable_EHCI_IRQ();
|
||||||
|
os_software_IRQ(DEV_EHCI);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int (*working_callback)(u32 flags)= NULL;
|
||||||
|
|
||||||
|
static void (*passive_callback)(u32 flags)= NULL;
|
||||||
|
|
||||||
|
static int private_timer_id=-1;
|
||||||
|
static int remote_message=0;
|
||||||
|
|
||||||
|
void ehci_int_working_callback_part1( int (*callback)(u32 flags), u32 timeout)
|
||||||
|
{
|
||||||
|
|
||||||
|
private_timer_id=os_create_timer(timeout, timeout*10, ehci1_queuehandle, 1);
|
||||||
|
|
||||||
|
swi_mload_set_register(0x0d800038,(1<<DEV_EHCI)); // clear interrupt flag
|
||||||
|
swi_mload_clr_register(0x0d80003c,(1<<DEV_EHCI)); // unmask interrupt flag
|
||||||
|
|
||||||
|
working_callback=callback;
|
||||||
|
|
||||||
|
ehci_writel (INTR_MASK, &ehci->regs->intr_enable);
|
||||||
|
|
||||||
|
os_software_IRQ(DEV_EHCI); // enable and mask interrupt flag
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int ehci_int_working_callback_part2(void)
|
||||||
|
{
|
||||||
|
static int message=0;
|
||||||
|
|
||||||
|
message=-ETIMEDOUT;
|
||||||
|
|
||||||
|
os_message_queue_receive(ehci1_queuehandle, (void*)&message, 0); // waits for interrupt or timeout
|
||||||
|
|
||||||
|
ehci_writel (0, &ehci->regs->intr_enable); // disable interrupts flags
|
||||||
|
working_callback=NULL; // disable callback
|
||||||
|
|
||||||
|
os_stop_timer(private_timer_id); // stops the timeout timer
|
||||||
|
os_destroy_timer(private_timer_id);
|
||||||
|
private_timer_id=-1;
|
||||||
|
|
||||||
|
|
||||||
|
if(message==0) // build message response
|
||||||
|
{
|
||||||
|
message=remote_message;
|
||||||
|
}
|
||||||
|
else message=-ETIMEDOUT;
|
||||||
|
|
||||||
|
os_software_IRQ(DEV_EHCI); // enable and mask interrupt flag
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ehci_int_passive_callback( void (*callback)(u32 flags))
|
||||||
|
{
|
||||||
|
|
||||||
|
passive_callback=callback;
|
||||||
|
working_callback=NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void int_send_device_message(int device);
|
||||||
|
|
||||||
|
|
||||||
|
int ehci_vector(void)
|
||||||
|
{
|
||||||
|
int ret=0;
|
||||||
|
u32 flags;
|
||||||
|
|
||||||
|
int message=1;
|
||||||
|
|
||||||
|
*((volatile u32 *)0x0d80003c ) &= ~(1<<DEV_EHCI); // disable EHCI interrupt
|
||||||
|
|
||||||
|
flags=ehci_readl (&ehci->regs->status);
|
||||||
|
|
||||||
|
if(working_callback)
|
||||||
|
{
|
||||||
|
|
||||||
|
message= working_callback(flags);
|
||||||
|
|
||||||
|
if(((int)message)<=0)
|
||||||
|
{
|
||||||
|
working_callback=NULL;
|
||||||
|
|
||||||
|
remote_message=message;
|
||||||
|
int_send_device_message(DEV_EHCI);
|
||||||
|
//ret=1;
|
||||||
|
|
||||||
|
ehci_writel (flags & INTR_MASK, &ehci->regs->status);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ehci_writel (flags & INTR_MASK, &ehci->regs->status);
|
||||||
|
//temp=ehci_readl( &ehci->regs->command);
|
||||||
|
|
||||||
|
*((volatile u32 *)0x0d80003c ) |= 1<<DEV_EHCI;
|
||||||
|
*((volatile u32 *)0x0d800038 ) |= 1<<DEV_EHCI;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(passive_callback)
|
||||||
|
{
|
||||||
|
|
||||||
|
passive_callback(flags);
|
||||||
|
ehci_writel (flags & INTR_MASK, &ehci->regs->status);
|
||||||
|
*((volatile u32 *)0x0d80003c ) |= 1<<DEV_EHCI;
|
||||||
|
*((volatile u32 *)0x0d800038 ) |= 1<<DEV_EHCI;
|
||||||
|
//ret=1; // remote int_send_device_message
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
ehci_writel (flags & INTR_MASK, &ehci->regs->status);
|
||||||
|
*((volatile u32 *)0x0d80003c ) |= 1<<DEV_EHCI;
|
||||||
|
*((volatile u32 *)0x0d800038 ) |= 1<<DEV_EHCI;
|
||||||
|
//ret=1; // remote int_send_device_message
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ret==1: send message to EHCI queue
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
28
ehcmodule/source/ehci_interrupt.h
Normal file
28
ehcmodule/source/ehci_interrupt.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef _EHCI_INTERRUPT_H_
|
||||||
|
#define _EHCI_INTERRUPT_H_
|
||||||
|
|
||||||
|
#include "syscalls.h"
|
||||||
|
#include "ehci_types.h"
|
||||||
|
#include "ehci.h"
|
||||||
|
|
||||||
|
#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
|
||||||
|
|
||||||
|
extern int heaphandle;
|
||||||
|
|
||||||
|
void enable_EHCI(void);
|
||||||
|
|
||||||
|
void disable_EHCI(void);
|
||||||
|
|
||||||
|
void enable_OHCI1(void);
|
||||||
|
|
||||||
|
void disable_OHCI1(void);
|
||||||
|
|
||||||
|
void init_thread_ehci(void);
|
||||||
|
|
||||||
|
void ehci_int_passive_callback( void (*callback)(u32 flags));
|
||||||
|
|
||||||
|
void ehci_int_working_callback_part1(int (*callback)(u32 flags), u32 timeout);
|
||||||
|
|
||||||
|
int ehci_int_working_callback_part2(void);
|
||||||
|
|
||||||
|
#endif
|
291
ehcmodule/source/main.c
Normal file
291
ehcmodule/source/main.c
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
/*
|
||||||
|
Custom IOS module for Wii.
|
||||||
|
Copyright (C) 2008 neimod.
|
||||||
|
|
||||||
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* main.c - IOS module main code
|
||||||
|
*
|
||||||
|
*******************************************************************************
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* v1.0 - 26 July 2008 - initial release by neimod
|
||||||
|
* v1.1 - 5 September 2008 - prepared for public release
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "syscalls.h"
|
||||||
|
#include "swi_mload.h"
|
||||||
|
|
||||||
|
int tiny_ehci_init(void);
|
||||||
|
|
||||||
|
//int ehc_loop(void);
|
||||||
|
|
||||||
|
u8 heap_space2[0xe000] __attribute__ ((aligned (32)));
|
||||||
|
|
||||||
|
/* USB timer */
|
||||||
|
|
||||||
|
|
||||||
|
int timer1_queuehandle=-1;
|
||||||
|
int timer1_id=-1;
|
||||||
|
|
||||||
|
void ehci_usleep(u32 time)
|
||||||
|
{
|
||||||
|
static u32 message;
|
||||||
|
//int n;
|
||||||
|
|
||||||
|
//os_message_queue_send(timer1_queuehandle, 0x555, 0);
|
||||||
|
//os_restart_timer(timer1_id, time);
|
||||||
|
timer1_id=os_create_timer(time, 1000*1000*10, timer1_queuehandle, 0x0);
|
||||||
|
os_message_queue_receive(timer1_queuehandle,(void *) &message, 0);
|
||||||
|
os_stop_timer(timer1_id);
|
||||||
|
os_destroy_timer(timer1_id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ehci_msleep(int msec)
|
||||||
|
{
|
||||||
|
ehci_usleep(((u32) msec)*1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define get_timer() (*(((volatile u32*)0x0D800010)))
|
||||||
|
|
||||||
|
void ehci_udelay(int usec)
|
||||||
|
{
|
||||||
|
u32 tmr,temp;
|
||||||
|
u32 time_usec;
|
||||||
|
|
||||||
|
tmr = get_timer();
|
||||||
|
time_usec=2*usec;
|
||||||
|
|
||||||
|
while (1) {temp=get_timer()-tmr;if(((int) temp)<0) tmr = get_timer(); if(((int)temp) > time_usec) break;}
|
||||||
|
|
||||||
|
}
|
||||||
|
void ehci_mdelay(int msec)//@todo not really sleeping..
|
||||||
|
{
|
||||||
|
u32 tmr,temp;
|
||||||
|
u32 time_usec;
|
||||||
|
|
||||||
|
tmr = get_timer();
|
||||||
|
time_usec=2048*msec;
|
||||||
|
|
||||||
|
while (1) {temp=get_timer()-tmr;if(((int) temp)<0) tmr = get_timer(); if(((int)temp) > time_usec) break;}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int ehc_loop(void);
|
||||||
|
|
||||||
|
int heaphandle=-1;
|
||||||
|
unsigned int heapspace[0x5000/*0x8800*/] __attribute__ ((aligned (32)));
|
||||||
|
|
||||||
|
|
||||||
|
void interrupt_vector(void);
|
||||||
|
void patch1_timer(void);
|
||||||
|
void patch2_timer_cont(void);
|
||||||
|
void int_send_device_message(u32);
|
||||||
|
|
||||||
|
void direct_os_sync_before_read(void* ptr, int size);
|
||||||
|
void direct_os_sync_after_write(void* ptr, int size);
|
||||||
|
void ic_invalidate(void);
|
||||||
|
|
||||||
|
static u32 vector[2]={ 0xE51FF004, 0}; // ldr pc,=addr
|
||||||
|
|
||||||
|
u32 syscall_base;
|
||||||
|
|
||||||
|
|
||||||
|
int my_di_os_message_queue_receive(int queuehandle, ipcmessage ** message,int flag);
|
||||||
|
|
||||||
|
u32 read_access_perm(void);
|
||||||
|
void write_access_perm(u32 flags);
|
||||||
|
|
||||||
|
static void di_patch(u32 addr1, u32 addr2)
|
||||||
|
{
|
||||||
|
u32 perm;
|
||||||
|
|
||||||
|
perm=read_access_perm();
|
||||||
|
write_access_perm(0xffffffff);
|
||||||
|
|
||||||
|
if(*((u32 *) addr2)==0xE6000170) // detect an unused syscall in dev/di to store the entry
|
||||||
|
{
|
||||||
|
vector[1]= ((u32) my_di_os_message_queue_receive) | 1;
|
||||||
|
memcpy((void *) addr2, vector, 8);
|
||||||
|
direct_os_sync_after_write((void *) addr2, 8);
|
||||||
|
|
||||||
|
*((u32 *) addr1)= 0xEA000000 | (((addr2-addr1)/4-2) & 0xFFFFFF); // change the jump
|
||||||
|
direct_os_sync_after_write((void *) addr1, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
write_access_perm(perm);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int copy_int_vect(u32 ios, u32 none)
|
||||||
|
{
|
||||||
|
ic_invalidate();
|
||||||
|
|
||||||
|
switch(ios)
|
||||||
|
{
|
||||||
|
case 36:
|
||||||
|
// WARNING!!!: IOS 36 ins not recommended because it fails using the ehcmodule some times
|
||||||
|
vector[1]= (u32) interrupt_vector;
|
||||||
|
|
||||||
|
memcpy((void *) 0xFFFF1E78, vector,8); // fix interrupt jump
|
||||||
|
direct_os_sync_after_write((void *) 0xFFFF1E78, 8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 37:
|
||||||
|
|
||||||
|
// patch for DI (IOS37 v3869) os_message_queue_receive() syscalls
|
||||||
|
di_patch(0x20205DE8, 0x2020408c);
|
||||||
|
|
||||||
|
vector[1]= (u32) 0xFFFF1F70;
|
||||||
|
memcpy((void *) patch1_timer, vector,8); // patch1 -> timer
|
||||||
|
direct_os_sync_after_write((void *) patch1_timer, 8);
|
||||||
|
|
||||||
|
vector[1]= (u32) 0xFFFF1F8C;
|
||||||
|
memcpy((void *) patch2_timer_cont, vector,8); // patch2-> next interrupt case
|
||||||
|
direct_os_sync_after_write((void *) patch2_timer_cont, 8);
|
||||||
|
|
||||||
|
vector[1]= (u32) 0xFFFF1E34;
|
||||||
|
memcpy((void *) int_send_device_message, vector,8); // patch3 ->send device message
|
||||||
|
direct_os_sync_after_write((void *) int_send_device_message, 8);
|
||||||
|
|
||||||
|
vector[1]= (u32) interrupt_vector;
|
||||||
|
|
||||||
|
memcpy((void *) 0xFFFF1F68, vector,8); // fix interrupt jump
|
||||||
|
direct_os_sync_after_write((void *) 0xFFFF1F68, 8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 38:
|
||||||
|
|
||||||
|
// patch for DI (IOS38 v3867) os_message_queue_receive() syscalls
|
||||||
|
di_patch(0x20205B14, 0x20203E6C);
|
||||||
|
|
||||||
|
vector[1]= (u32) 0xFFFF1EB0;
|
||||||
|
memcpy((void *) patch1_timer, vector, 8); // patch1 -> timer
|
||||||
|
direct_os_sync_after_write((void *) patch1_timer, 8);
|
||||||
|
|
||||||
|
vector[1]= (u32) 0xFFFF1ECC;
|
||||||
|
memcpy((void *) patch2_timer_cont, vector, 8); // patch2-> next interrupt case
|
||||||
|
direct_os_sync_after_write((void *) patch2_timer_cont, 8);
|
||||||
|
|
||||||
|
vector[1]= (u32) 0xFFFF1D74;
|
||||||
|
memcpy((void *) int_send_device_message, vector, 8); // patch3 ->send device message
|
||||||
|
direct_os_sync_after_write((void *) int_send_device_message, 8);
|
||||||
|
|
||||||
|
vector[1]= (u32) interrupt_vector;
|
||||||
|
|
||||||
|
memcpy((void *) 0xFFFF1EA8, vector,8);
|
||||||
|
direct_os_sync_after_write((void *) 0xFFFF1EA8, 8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 57:
|
||||||
|
// patch for DI (IOS57 v5661) os_message_queue_receive() syscalls
|
||||||
|
di_patch(0x20205E84, 0x20203F60);
|
||||||
|
|
||||||
|
vector[1]= (u32) 0xFFFF2130;
|
||||||
|
memcpy((void *) patch1_timer, vector,8); // patch1 -> timer
|
||||||
|
direct_os_sync_after_write((void *) patch1_timer, 8);
|
||||||
|
|
||||||
|
vector[1]= (u32) 0xFFFF214C;
|
||||||
|
memcpy((void *) patch2_timer_cont, vector,8); // patch2-> next interrupt case
|
||||||
|
direct_os_sync_after_write((void *) patch2_timer_cont, 8);
|
||||||
|
|
||||||
|
vector[1]= (u32) 0xFFFF1FF4;
|
||||||
|
memcpy((void *) int_send_device_message, vector,8); // patch3 ->send device message
|
||||||
|
direct_os_sync_after_write((void *) int_send_device_message, 8);
|
||||||
|
|
||||||
|
vector[1]= (u32) interrupt_vector;
|
||||||
|
|
||||||
|
memcpy((void *) 0xFFFF2128, vector,8); // fix interrupt jump
|
||||||
|
direct_os_sync_after_write((void *) 0xFFFF2128, 8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 60:
|
||||||
|
|
||||||
|
// patch for DI (IOS60 v6174) os_message_queue_receive() syscalls
|
||||||
|
di_patch(0x20205D94, 0x20203F60);
|
||||||
|
|
||||||
|
vector[1]= (u32) 0xFFFF2130;
|
||||||
|
memcpy((void *) patch1_timer, vector,8); // patch1 -> timer
|
||||||
|
direct_os_sync_after_write((void *) patch1_timer, 8);
|
||||||
|
|
||||||
|
vector[1]= (u32) 0xFFFF214C;
|
||||||
|
memcpy((void *) patch2_timer_cont, vector,8); // patch2-> next interrupt case
|
||||||
|
direct_os_sync_after_write((void *) patch2_timer_cont, 8);
|
||||||
|
|
||||||
|
vector[1]= (u32) 0xFFFF1FF4;
|
||||||
|
memcpy((void *) int_send_device_message, vector,8); // patch3 ->send device message
|
||||||
|
direct_os_sync_after_write((void *) int_send_device_message, 8);
|
||||||
|
|
||||||
|
vector[1]= (u32) interrupt_vector;
|
||||||
|
|
||||||
|
memcpy((void *) 0xFFFF2128, vector,8); // fix interrupt jump
|
||||||
|
direct_os_sync_after_write((void *) 0xFFFF2128, 8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//*((volatile u32 *)0x0d8000c0) |=0x20;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern char use_usb_port1;
|
||||||
|
extern u32 current_port;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
current_port= ((u32) use_usb_port1)!=0;
|
||||||
|
// changes IOS vector interrupt to crt0.s routine
|
||||||
|
|
||||||
|
//swi_mload_led_on();
|
||||||
|
|
||||||
|
|
||||||
|
syscall_base=swi_mload_get_syscall_base();
|
||||||
|
os_sync_after_write((void *) &syscall_base, 4);
|
||||||
|
|
||||||
|
swi_mload_call_func((void *) copy_int_vect, (void *) swi_mload_get_ios_base(), NULL);
|
||||||
|
|
||||||
|
|
||||||
|
heaphandle = os_heap_create(heapspace, sizeof(heapspace));
|
||||||
|
|
||||||
|
void* timer1_queuespace = os_heap_alloc(heaphandle, 0x80);
|
||||||
|
|
||||||
|
timer1_queuehandle = os_message_queue_create(timer1_queuespace, 32);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(tiny_ehci_init()<0) return -1;
|
||||||
|
|
||||||
|
|
||||||
|
ehc_loop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
367
ehcmodule/source/tiny_ehci_glue.c
Normal file
367
ehcmodule/source/tiny_ehci_glue.c
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
/*
|
||||||
|
EHCI glue. A bit hacky for the moment. needs cleaning..
|
||||||
|
|
||||||
|
Copyright (C) 2008 kwiirk.
|
||||||
|
|
||||||
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include "syscalls.h"
|
||||||
|
|
||||||
|
#include "ehci_types.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "ehci_interrupt.h"
|
||||||
|
#include "swi_mload.h"
|
||||||
|
|
||||||
|
#define static
|
||||||
|
#define inline extern
|
||||||
|
|
||||||
|
|
||||||
|
#define readl(a) (*((volatile u32*)(a)))
|
||||||
|
#define writel(v,a) do{*((volatile u32*)(a))=(v);}while(0)
|
||||||
|
#define ehci_dbg(a...) debug_printf(a)
|
||||||
|
#define printk(a...) debug_printf(a)
|
||||||
|
#define get_timer() (*(((volatile u32*)0x0D800010)))
|
||||||
|
|
||||||
|
|
||||||
|
void BUG(void)
|
||||||
|
{
|
||||||
|
debug_printf("bug\n");
|
||||||
|
// stack_trace();
|
||||||
|
// while(1);
|
||||||
|
}
|
||||||
|
#define BUG_ON(a) if(a)BUG()
|
||||||
|
|
||||||
|
void ehci_usleep(int usec);
|
||||||
|
void ehci_msleep(int msec);
|
||||||
|
/*
|
||||||
|
void udelay(int usec)
|
||||||
|
{
|
||||||
|
u32 tmr,temp;
|
||||||
|
u32 time_usec;
|
||||||
|
|
||||||
|
tmr = get_timer();
|
||||||
|
time_usec=2*usec;
|
||||||
|
|
||||||
|
while (1) {temp=get_timer()-tmr;if(temp > time_usec) break;}
|
||||||
|
|
||||||
|
}
|
||||||
|
void msleep(int msec)//@todo not really sleeping..
|
||||||
|
{
|
||||||
|
u32 tmr,temp;
|
||||||
|
u32 time_usec;
|
||||||
|
|
||||||
|
tmr = get_timer();
|
||||||
|
time_usec=2048*msec;
|
||||||
|
|
||||||
|
while (1) {temp=get_timer()-tmr;if(temp > time_usec) break;}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
extern u32 __exe_start_virt__;
|
||||||
|
extern u32 __ram_start_virt__;
|
||||||
|
|
||||||
|
extern u32 ios_thread_stack;
|
||||||
|
|
||||||
|
#define cpu_to_le32(a) swab32(a)
|
||||||
|
#define le32_to_cpu(a) swab32(a)
|
||||||
|
#define cpu_to_le16(a) swab16(a)
|
||||||
|
#define le16_to_cpu(a) swab16(a)
|
||||||
|
#define cpu_to_be32(a) (a)
|
||||||
|
#define be32_to_cpu(a) (a)
|
||||||
|
void print_hex_dump_bytes(char *header,int prefix,u8 *buf,int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (len>0x100)len=0x100;
|
||||||
|
debug_printf("%s %08X\n",header,(u32)buf);
|
||||||
|
for (i=0;i<len;i++){
|
||||||
|
debug_printf("%02x ",buf[i]);
|
||||||
|
if((i&0xf) == 0xf)
|
||||||
|
debug_printf("\n");
|
||||||
|
}
|
||||||
|
debug_printf("\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
#define DUMP_PREFIX_OFFSET 1
|
||||||
|
#include "ehci.h"
|
||||||
|
#define ehci_readl(a) ((*((volatile u32*)(a))))
|
||||||
|
//#define ehci_writel(e,v,a) do{msleep(40);debug_printf("writel %08X %08X\n",a,v);*((volatile u32*)(a))=(v);}while(0)
|
||||||
|
#define ehci_writel(v,a) do{*((volatile u32*)(a))=(v);}while(0)
|
||||||
|
|
||||||
|
struct ehci_hcd _ehci;
|
||||||
|
struct ehci_hcd *ehci = &_ehci;
|
||||||
|
|
||||||
|
#include "ehci.c"
|
||||||
|
|
||||||
|
|
||||||
|
int usb_os_init(void);
|
||||||
|
|
||||||
|
#define MLOAD_GET_EHCI_DATA 0x4D4C44A0
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
|
||||||
|
int system_cmd(int cmd)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static struct ehci_qtd *qtd_dummy_first=NULL ;
|
||||||
|
static struct ehci_qtd * qtd_header=NULL;
|
||||||
|
static struct ehci_qh * qh_header=NULL;
|
||||||
|
//void *global_buffer=NULL;
|
||||||
|
|
||||||
|
struct ehci_qh * qh_pointer[64];
|
||||||
|
|
||||||
|
extern struct ehci_qh *in_qh;
|
||||||
|
extern struct ehci_qh *out_qh;
|
||||||
|
extern struct ehci_qh *dummy_qh;
|
||||||
|
|
||||||
|
|
||||||
|
inline dma_addr_t get_qtd_dummy(void)
|
||||||
|
{
|
||||||
|
return qtd_dummy_first->qtd_dma;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_qh_and_qtd(void)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
struct ehci_qtd * qtd;
|
||||||
|
|
||||||
|
struct ehci_qh * qh;
|
||||||
|
|
||||||
|
if(!qh_header)
|
||||||
|
{
|
||||||
|
//u32 mem = (u32) USB_Alloc(4096*3);
|
||||||
|
//mem=(mem+4095) & ~4095;
|
||||||
|
qh_header= (struct ehci_qh *) ehci->async;//mem;
|
||||||
|
qtd_header= (struct ehci_qtd *) ehci->qtds[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
qtd=qtd_header;//= (struct ehci_qtd *) (((u32)qh_header)+4096);
|
||||||
|
|
||||||
|
for(n=0;n<EHCI_MAX_QTD;n++)
|
||||||
|
{
|
||||||
|
|
||||||
|
ehci->qtds[n]=qtd;
|
||||||
|
|
||||||
|
memset((void *) ehci->qtds[n], 0, sizeof(struct ehci_qtd));
|
||||||
|
ehci_dma_map_bidir((void *) ehci->qtds[n],sizeof(struct ehci_qtd));
|
||||||
|
|
||||||
|
qtd=(struct ehci_qtd *) (((((u32) qtd)+sizeof(struct ehci_qtd)+31) & ~31));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(n=0;n<EHCI_MAX_QTD;n++)
|
||||||
|
{
|
||||||
|
|
||||||
|
memset((void *) qtd, 0, sizeof(struct ehci_qtd));
|
||||||
|
ehci_dma_map_bidir((void *) qtd,sizeof(struct ehci_qtd));
|
||||||
|
|
||||||
|
qtd=(struct ehci_qtd *) (((((u32) qtd)+sizeof(struct ehci_qtd)+31) & ~31));
|
||||||
|
}
|
||||||
|
|
||||||
|
qtd_dummy_first=qtd;
|
||||||
|
|
||||||
|
qh=qh_header;
|
||||||
|
|
||||||
|
for(n=0;n<6;n++)
|
||||||
|
{
|
||||||
|
|
||||||
|
qh_pointer[n]=qh;
|
||||||
|
|
||||||
|
memset((void *) qh_pointer[n], 0, sizeof(struct ehci_qh));
|
||||||
|
qh->qh_dma = ehci_virt_to_dma(qh);
|
||||||
|
qh_pointer[n]->hw_info1 = cpu_to_hc32((QH_HEAD*(n!=0)));
|
||||||
|
qh_pointer[n]->hw_info2 = cpu_to_hc32(0);
|
||||||
|
qh_pointer[n]->hw_token = cpu_to_hc32( QTD_STS_HALT);
|
||||||
|
qh=(struct ehci_qh *) (((((u32) qh)+sizeof(struct ehci_qh)+31) & ~31));
|
||||||
|
qh_pointer[n]->hw_next = QH_NEXT( ehci_virt_to_dma(qh));
|
||||||
|
qh_pointer[n]->hw_qtd_next =EHCI_LIST_END();
|
||||||
|
qh_pointer[n]->hw_alt_next = EHCI_LIST_END();
|
||||||
|
|
||||||
|
ehci_dma_map_bidir((void *) qh_pointer[n],sizeof(struct ehci_qh));
|
||||||
|
}
|
||||||
|
n--;
|
||||||
|
qh_pointer[n]->hw_next = QH_NEXT( ehci_virt_to_dma(qh_header));
|
||||||
|
ehci_dma_map_bidir((void *) qh_pointer[n],sizeof(struct ehci_qh));
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_qtd_dummy(void)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
struct ehci_qtd * qtd, *qtd_next;
|
||||||
|
|
||||||
|
|
||||||
|
qtd=qtd_dummy_first;
|
||||||
|
|
||||||
|
for(n=0;;n++)
|
||||||
|
{
|
||||||
|
qtd_next=(struct ehci_qtd *) (((((u32) qtd)+sizeof(struct ehci_qtd)+31) & ~31));
|
||||||
|
ehci_qtd_init(qtd);
|
||||||
|
|
||||||
|
//qtd_fill( qtd, 0, 0, QTD_STS_HALT, 0);
|
||||||
|
if(n<3)
|
||||||
|
{
|
||||||
|
qtd->hw_next= QTD_NEXT(qtd_next->qtd_dma);
|
||||||
|
qtd->hw_alt_next= EHCI_LIST_END(); //QTD_NEXT(qtd_next->qtd_dma);
|
||||||
|
ehci_dma_map_bidir((void *) qtd,sizeof(struct ehci_qtd));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ehci_dma_map_bidir(qtd,sizeof(struct ehci_qtd));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
qtd=qtd_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
int hola(void *i, void *o)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
for(n=0;n<10;n++)
|
||||||
|
{
|
||||||
|
*((volatile u32 *)0x0d8000c0) ^=0x20;
|
||||||
|
ehci_mdelay(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void reinit_ehci_headers(void)
|
||||||
|
{
|
||||||
|
init_qh_and_qtd();
|
||||||
|
|
||||||
|
create_qtd_dummy();
|
||||||
|
|
||||||
|
ehci->async= qh_pointer[0];
|
||||||
|
ehci->asyncqh= qh_pointer[1];
|
||||||
|
in_qh=qh_pointer[2];
|
||||||
|
out_qh=qh_pointer[3];
|
||||||
|
dummy_qh=qh_pointer[4];
|
||||||
|
|
||||||
|
ehci_dma_unmap_bidir((dma_addr_t) ehci->async,sizeof(struct ehci_qh));
|
||||||
|
|
||||||
|
ehci->async->ehci = ehci;
|
||||||
|
ehci->async->qtd_head = NULL;
|
||||||
|
ehci->async->qh_dma = ehci_virt_to_dma(ehci->async);
|
||||||
|
ehci->async->hw_next = QH_NEXT(dummy_qh->qh_dma/* ehci->async->qh_dma*/);
|
||||||
|
ehci->async->hw_info1 = cpu_to_hc32( QH_HEAD);
|
||||||
|
ehci->async->hw_info2 = cpu_to_hc32( 0);
|
||||||
|
ehci->async->hw_token = cpu_to_hc32( QTD_STS_HALT);
|
||||||
|
|
||||||
|
|
||||||
|
ehci->async->hw_qtd_next =EHCI_LIST_END();
|
||||||
|
ehci->async->hw_alt_next =EHCI_LIST_END(); //QTD_NEXT(get_qtd_dummy());
|
||||||
|
|
||||||
|
ehci_dma_map_bidir(ehci->async,sizeof(struct ehci_qh));
|
||||||
|
|
||||||
|
ehci_dma_unmap_bidir((dma_addr_t)ehci->asyncqh,sizeof(struct ehci_qh));
|
||||||
|
ehci->asyncqh->ehci = ehci;
|
||||||
|
ehci->asyncqh->qtd_head = NULL;
|
||||||
|
ehci->asyncqh->qh_dma = ehci_virt_to_dma(ehci->asyncqh);
|
||||||
|
|
||||||
|
ehci_dma_unmap_bidir((dma_addr_t)in_qh,sizeof(struct ehci_qh));
|
||||||
|
in_qh->ehci = ehci;
|
||||||
|
in_qh->qtd_head = NULL;
|
||||||
|
in_qh->qh_dma = ehci_virt_to_dma(in_qh);
|
||||||
|
ehci_dma_map_bidir(in_qh,sizeof(struct ehci_qh));
|
||||||
|
|
||||||
|
ehci_dma_unmap_bidir((dma_addr_t)out_qh,sizeof(struct ehci_qh));
|
||||||
|
out_qh->ehci = ehci;
|
||||||
|
out_qh->qtd_head = NULL;
|
||||||
|
out_qh->qh_dma = ehci_virt_to_dma(out_qh);
|
||||||
|
ehci_dma_map_bidir(out_qh,sizeof(struct ehci_qh));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int tiny_ehci_init(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
ehci = &_ehci;
|
||||||
|
|
||||||
|
|
||||||
|
if(usb_os_init()<0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(1)
|
||||||
|
{ // From Hermes: ohci mem is readed from dev/mload: (ehci init is from here)
|
||||||
|
/* int fd;
|
||||||
|
fd = os_open("/dev/mload",1);
|
||||||
|
if(fd<0) return -1;
|
||||||
|
ehci= (struct ehci_hcd *) os_ioctlv(fd, MLOAD_GET_EHCI_DATA ,0,0,0);
|
||||||
|
|
||||||
|
os_close(fd);
|
||||||
|
*/
|
||||||
|
ehci=swi_mload_EHCI_data();
|
||||||
|
|
||||||
|
// stops EHCI
|
||||||
|
ehci_writel( 0x00010020 , &ehci->regs->command);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(!(ehci_readl( &ehci->regs->command) & 1))break;
|
||||||
|
} while(1);
|
||||||
|
|
||||||
|
|
||||||
|
ehci_dma_map_bidir(ehci,sizeof(struct ehci_hcd));
|
||||||
|
|
||||||
|
for (i = 0; i < DEFAULT_I_TDPS; i++)
|
||||||
|
{
|
||||||
|
ehci->periodic [i] = EHCI_LIST_END();
|
||||||
|
ehci_dma_map_bidir((void *) ehci->periodic [i],4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
reinit_ehci_headers();
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/* WARNING: This ignore the port 1 (external) and 2,3 (internals) for USB 2.0 operations */
|
||||||
|
/* from cIOS mload 1.6 port 1 is forced to USB 1.1. Only port 0 can work as USB 2.0 */
|
||||||
|
|
||||||
|
ehci->num_port=2;
|
||||||
|
ehci_release_ports();
|
||||||
|
|
||||||
|
//ehci_writel( 0x00080021, &ehci->regs->command);
|
||||||
|
//ehci_writel(0, &ehci->regs->frame_list);
|
||||||
|
|
||||||
|
ehci_writel(ehci->async->qh_dma, &ehci->regs->async_next);
|
||||||
|
ehci_writel (/*INTR_MASK*/STS_PCD, &ehci->regs->intr_enable);
|
||||||
|
#define t125us (1)
|
||||||
|
ehci_writel( (t125us<<16) | 0x0021 , &ehci->regs->command);
|
||||||
|
ehci_readl( &ehci->regs->command);
|
||||||
|
|
||||||
|
//swi_mload_led_on();
|
||||||
|
//swi_mload_call_func(hola,NULL,NULL);
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
90
ehcmodule/source/usb_os.c
Normal file
90
ehcmodule/source/usb_os.c
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#include "syscalls.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "ehci_types.h"
|
||||||
|
#include "usb.h"
|
||||||
|
#include "ehci.h"
|
||||||
|
|
||||||
|
static int heap=-1;
|
||||||
|
|
||||||
|
void ehci_usleep(int usec);
|
||||||
|
void ehci_msleep(int msec);
|
||||||
|
|
||||||
|
extern u8 heap_space2[0xe000];
|
||||||
|
|
||||||
|
int usb_os_init(void)
|
||||||
|
{
|
||||||
|
heap = os_heap_create(heap_space2, 0xe000);
|
||||||
|
//heap = os_heap_create((void*)0x13890000, 0x8000);
|
||||||
|
if(heap<0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_cache_data(char *in, int len)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
char t;
|
||||||
|
|
||||||
|
for(n=0;n<len;n++) t=*in++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_addr_t ehci_virt_to_dma(void *a)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (dma_addr_t)a;
|
||||||
|
}
|
||||||
|
dma_addr_t ehci_dma_map_to(void *buf,size_t len)
|
||||||
|
{
|
||||||
|
os_sync_after_write(buf, len);
|
||||||
|
return (dma_addr_t)buf;
|
||||||
|
|
||||||
|
}
|
||||||
|
dma_addr_t ehci_dma_map_from(void *buf,size_t len)
|
||||||
|
{
|
||||||
|
os_sync_after_write(buf, len);
|
||||||
|
return (dma_addr_t)buf;
|
||||||
|
}
|
||||||
|
dma_addr_t ehci_dma_map_bidir(void *buf,size_t len)
|
||||||
|
{
|
||||||
|
//debug_printf("sync_after_write %p %x\n",buf,len);
|
||||||
|
|
||||||
|
os_sync_after_write(buf, len);
|
||||||
|
return (dma_addr_t)buf;
|
||||||
|
}
|
||||||
|
void ehci_dma_unmap_to(dma_addr_t buf,size_t len)
|
||||||
|
{
|
||||||
|
os_sync_before_read((void*)buf, len);
|
||||||
|
read_cache_data((void *) buf, len);
|
||||||
|
}
|
||||||
|
void ehci_dma_unmap_from(dma_addr_t buf,size_t len)
|
||||||
|
{
|
||||||
|
os_sync_before_read((void*)buf, len);
|
||||||
|
read_cache_data((void *) buf, len);
|
||||||
|
}
|
||||||
|
void ehci_dma_unmap_bidir(dma_addr_t buf,size_t len)
|
||||||
|
{
|
||||||
|
os_sync_before_read((void*)buf, len);
|
||||||
|
read_cache_data((void *) buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void *USB_Alloc(int size)
|
||||||
|
{
|
||||||
|
void * ret = 0;
|
||||||
|
ret= os_heap_alloc_aligned(heap, size, 32);
|
||||||
|
// ret= os_heap_alloc(heap, size);
|
||||||
|
if(ret==0)
|
||||||
|
{
|
||||||
|
os_puts("USB Alloc: not enough memory!\n");
|
||||||
|
while(1) {swi_mload_led_on();ehci_msleep(200);swi_mload_led_off();ehci_msleep(200);}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
void USB_Free(void *ptr)
|
||||||
|
{
|
||||||
|
return os_heap_free(heap, ptr);
|
||||||
|
}
|
||||||
|
|
131
ehcmodule/source/wbfs_glue.c
Normal file
131
ehcmodule/source/wbfs_glue.c
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
Custom IOS module for Wii.
|
||||||
|
wbfs glue
|
||||||
|
Copyright (C) 2009 kwiirk.
|
||||||
|
Copyright (C) 2008 neimod.
|
||||||
|
|
||||||
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* oh0_loop.c - IOS module main code
|
||||||
|
* even if we are "ehc" driver, we still pretend to be "oh0"
|
||||||
|
* and implement "standard" ios oh0 usb api
|
||||||
|
*
|
||||||
|
*******************************************************************************
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "syscalls.h"
|
||||||
|
#include "libwbfs.h"
|
||||||
|
|
||||||
|
u32 n_sec,sec_size;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ int read_sector(void *ign,u32 lba,u32 count,void*buf)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
|
os_sync_after_write(buf, count*sec_size);
|
||||||
|
|
||||||
|
/* do
|
||||||
|
{*/
|
||||||
|
ret = USBStorage_Read_Sectors(lba,count, buf);
|
||||||
|
/*}*/
|
||||||
|
if(!ret) return 1;
|
||||||
|
|
||||||
|
os_sync_before_read(buf, count*sec_size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static wbfs_disc_t *wbfs_disc=NULL;
|
||||||
|
|
||||||
|
u8 *disc_buff=NULL;
|
||||||
|
extern u32 current_disc_lba;
|
||||||
|
|
||||||
|
|
||||||
|
void wbfs_perform_disc(void)
|
||||||
|
{
|
||||||
|
if(wbfs_disc)
|
||||||
|
{
|
||||||
|
|
||||||
|
wbfs_close_disc(wbfs_disc);wbfs_disc=NULL;
|
||||||
|
}
|
||||||
|
if(!disc_buff) {disc_buff=WBFS_Alloc(0x8020);}
|
||||||
|
|
||||||
|
current_disc_lba=0xffffffff;
|
||||||
|
|
||||||
|
}
|
||||||
|
static wbfs_t *p=NULL;
|
||||||
|
|
||||||
|
void release_wbfs_mem(void)
|
||||||
|
{
|
||||||
|
if(disc_buff) WBFS_Free(disc_buff);disc_buff=NULL;
|
||||||
|
|
||||||
|
if(wbfs_disc)
|
||||||
|
{
|
||||||
|
wbfs_close_disc(wbfs_disc);wbfs_disc=NULL;
|
||||||
|
}
|
||||||
|
if(p)
|
||||||
|
wbfs_close(p);p= NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
wbfs_disc_t * wbfs_init_with_partition(u8*discid, int partition)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
static u8 old_discid[6]="";
|
||||||
|
|
||||||
|
if(disc_buff) WBFS_Free(disc_buff);disc_buff=NULL;
|
||||||
|
|
||||||
|
// opens the hd only is is not opened
|
||||||
|
if(!p)
|
||||||
|
{
|
||||||
|
USBStorage_Init();
|
||||||
|
n_sec = USBStorage_Get_Capacity(&sec_size);
|
||||||
|
//debug_printf("hd found n_sec:%x sec_size %x\n",n_sec,sec_size);
|
||||||
|
if (n_sec==0)
|
||||||
|
return NULL; //no hd
|
||||||
|
p = wbfs_open_hd(read_sector, 0, 0, sec_size, n_sec,partition, 0);
|
||||||
|
if(!p) // no partition
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// close previously disc opened except if discid is equal
|
||||||
|
if(wbfs_disc)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(!memcmp(old_discid,discid,6)) return wbfs_disc;
|
||||||
|
|
||||||
|
wbfs_close_disc(wbfs_disc);wbfs_disc=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open the disc
|
||||||
|
wbfs_disc=wbfs_open_disc(p, discid);
|
||||||
|
|
||||||
|
if(wbfs_disc) memcpy(old_discid,discid,6);
|
||||||
|
|
||||||
|
return wbfs_disc;
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
1
gui.pnps
1
gui.pnps
@ -1 +0,0 @@
|
|||||||
<pd><ViewState><e p="gui" x="true"></e><e p="gui\source" x="false"></e></ViewState></pd>
|
|
10
libcios/include/ios_usbstorage.h
Normal file
10
libcios/include/ios_usbstorage.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef IOS_USBSTORAGE_H
|
||||||
|
#define IOS_USBSTORAGE_H
|
||||||
|
#include "syscalls.h"
|
||||||
|
|
||||||
|
void ums_init(void);
|
||||||
|
s32 ums_read_sectors(u32 sector, u32 numSectors, void *buffer);
|
||||||
|
void ums_close(void);
|
||||||
|
void *ums_alloc(int size);
|
||||||
|
void ums_free(void *ptr);
|
||||||
|
#endif
|
92
libcios/include/starlet.h
Normal file
92
libcios/include/starlet.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#ifndef STARLET_H
|
||||||
|
#define STARLET_H
|
||||||
|
|
||||||
|
// info from wiibrew.org
|
||||||
|
|
||||||
|
// IRQS (32 bits registers)
|
||||||
|
|
||||||
|
/*
|
||||||
|
IRQ Description
|
||||||
|
|
||||||
|
0 Starlet Timer
|
||||||
|
1 NAND Interface
|
||||||
|
2 AES Engine
|
||||||
|
3 SHA-1 Engine
|
||||||
|
4 USB Host Controller (EHCI)
|
||||||
|
5 USB Host Controller (OHCI0)
|
||||||
|
6 USB Host Controller (OHCI1)
|
||||||
|
7 SD Host Controller
|
||||||
|
8 802.11 Wireless
|
||||||
|
9 Unknown
|
||||||
|
10 Hollywood GPIOs (Broadway)
|
||||||
|
11 Hollywood GPIOs (Starlet)
|
||||||
|
12-16 Unknown
|
||||||
|
17 Reset button
|
||||||
|
18-29 Unknown
|
||||||
|
30 IPC (Broadway)
|
||||||
|
31 IPC (Starlet)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HW_PPCIRQFLAG 0x0d800030 // Broadway IRQ Flags (write 1 to clear)
|
||||||
|
#define HW_PPCIRQMASK 0x0d800034 // Broadway IRQ Mask (write 1 to set)
|
||||||
|
#define HW_ARMIRQFLAG 0x0d800038 // Starlet IRQ Flags (write 1 to clear)
|
||||||
|
#define HW_ARMIRQMASK 0x0d80003c // Starlet IRQ Mask (write 1 to set)
|
||||||
|
|
||||||
|
// GPIOS (32 bits registers)
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Bit Direction Connection Description
|
||||||
|
|
||||||
|
0 IN POWER Power button input (pulse width limited; will not detect a held-down state).
|
||||||
|
1 OUT SHUTDOWN Output high to turn system off (Power LED = red).
|
||||||
|
2 OUT FAN Fan power, active high.
|
||||||
|
3 OUT DC_DC DC/DC converter power, active high (powers the Broadway?[check]). When off, also triggers the Yellow power LED.
|
||||||
|
4 OUT DI_SPIN DI spinup disable. If clear, the drive attempts to spin up a disc when reset (if there is one in the drive). If set, the drive ignores a present disc when reset.
|
||||||
|
5 OUT SLOT_LED Blue disc slot LED, active high.
|
||||||
|
6 IN EJECT_BTN Eject button (pulse width limited). Button press will also trigger the drive directly.
|
||||||
|
7 IN SLOT_IN Disc slot optical detector. High if disc in drive, disc being inserted, or disc still in slot after eject.
|
||||||
|
8 OUT SENSOR_BAR Sensor bar, active high.
|
||||||
|
9 OUT DO_EJECT Pulse high to trigger a DI eject from software.
|
||||||
|
10 OUT EEP_CS SEEPROM Chip Select.
|
||||||
|
11 OUT EEP_CLK SEEPROM Clock.
|
||||||
|
12 OUT EEP_MOSI Data to SEEPROM.
|
||||||
|
13 IN EEP_MISO Data from SEEPROM.
|
||||||
|
14 OUT AVE_SCL A/V Encoder I²C Clock.
|
||||||
|
15 I/O AVE_SDA A/V Encoder I²C Data (has an external pull-up, so you should only drive it low).
|
||||||
|
16 OUT DEBUG0 Debug Testpoint TP221.
|
||||||
|
17 OUT DEBUG1 Debug Testpoint TP222.
|
||||||
|
18 OUT DEBUG2 Debug Testpoint TP223.
|
||||||
|
19 OUT DEBUG3 Debug Testpoint TP224.
|
||||||
|
20 OUT DEBUG4 Debug Testpoint TP225.
|
||||||
|
21 OUT DEBUG5 Debug Testpoint TP226.
|
||||||
|
22 OUT DEBUG6 Debug Testpoint TP219.
|
||||||
|
23 OUT DEBUG7 Debug Testpoint TP220.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HW_GPIOB_OUT 0x0d8000c0 // GPIO Outputs (Broadway access)
|
||||||
|
#define HW_GPIOB_DIR 0x0d8000c4 // GPIO Direction (Broadway access)
|
||||||
|
#define HW_GPIOB_IN 0x0d8000c8 // GPIO Inputs (Broadway access)
|
||||||
|
#define HW_GPIOB_INTLVL 0x0d8000cc // GPIO Interrupt Levels (Broadway access)
|
||||||
|
#define HW_GPIOB_INTFLAG 0x0d8000d0 // GPIO Interrupt Flags (Broadway access)
|
||||||
|
#define HW_GPIOB_INTMASK 0x0d8000d4 // GPIO Interrupt Masks (Broadway access)
|
||||||
|
#define HW_GPIOB_INMIR 0x0d8000d8 // GPIO Input Mirror (Broadway access)
|
||||||
|
#define HW_GPIO_ENABLE 0x0d8000dc // GPIO Enable (Starlet only)
|
||||||
|
#define HW_GPIO_OUT 0x0d8000e0 // GPIO Outputs (Starlet only)
|
||||||
|
#define HW_GPIO_DIR 0x0d8000e4 // GPIO Direction (Starlet only)
|
||||||
|
#define HW_GPIO_IN 0x0d8000e8 // GPIO Inputs (Starlet only)
|
||||||
|
#define HW_GPIO_INTLVL 0x0d8000ec // GPIO Interrupt Levels (Starlet only)
|
||||||
|
#define HW_GPIO_INTFLAG 0x0d8000f0 // GPIO Interrupt Flags (Starlet only)
|
||||||
|
#define HW_GPIO_INTMASK 0x0d8000f4 // GPIO Interrupt Masks (Starlet only)
|
||||||
|
#define HW_GPIO_INMIR 0x0d8000f8 // GPIO Input Mirror (Starlet only)
|
||||||
|
#define HW_GPIO_OWNER 0x0d8000fc // GPIO Owner Select (Starlet only)
|
||||||
|
|
||||||
|
// TIMER (32 bits registers)
|
||||||
|
|
||||||
|
#define HW_TIMER 0x0d800010 // Timer counter
|
||||||
|
#define HW_ALARM 0x0d800014 // Alarm value
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
233
libcios/include/swi_mload.h
Normal file
233
libcios/include/swi_mload.h
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
/* SWI service from dev/mload (c) 2009 Hermes / www.elotrolado.net */
|
||||||
|
|
||||||
|
#ifndef IOS_SWI_MLOAD_H
|
||||||
|
#define IOS_SWI_MLOAD_H
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "starlet.h"
|
||||||
|
|
||||||
|
/* NOTE: stack for SWI services is 0x900 bytes */
|
||||||
|
/* WARNING: Interrupt are disabled in SWI functions and you cannot call syscalls */
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_add_handler: add a new service handler for SWI
|
||||||
|
|
||||||
|
svc_code: for example 0xab for svc 0xab
|
||||||
|
|
||||||
|
func: function for the new SWI service
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_add_handler(u8 svc_code, int (*func) (u32 arg0, u32 arg1, u32 arg2, u32 arg3));
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_EHCI_data: gets the EHCI struct from dev/mload
|
||||||
|
|
||||||
|
return: the struct pointer
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * swi_mload_EHCI_data(void);
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_get_syscall_base: gets the syscall base address to call directly
|
||||||
|
|
||||||
|
return: the address
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
u32 swi_mload_get_syscall_base(void);
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_get_ios_base: gets the ios base (FFS, ES, IOSP) used to create this cIOS
|
||||||
|
|
||||||
|
return: the IOS base version
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
u32 swi_mload_get_ios_base(void);
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_memcpy: memcpy from supervisor mode
|
||||||
|
|
||||||
|
dst: destination address
|
||||||
|
|
||||||
|
src: source address
|
||||||
|
|
||||||
|
len: datas to move
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_memcpy(void * dst, void * src, int len);
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_memcpy_from_uncached: memcpy from supervisor mode. Copies from uncached source RAM to cached RAM
|
||||||
|
|
||||||
|
dst: destination address
|
||||||
|
|
||||||
|
src: source address uncached
|
||||||
|
|
||||||
|
len: datas to move
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_memcpy_from_uncached(void * dst, void * src, int len);
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_get_register: function thinking to read 32 bits registers from supervisor mode
|
||||||
|
|
||||||
|
addr: register address
|
||||||
|
|
||||||
|
return: value
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
u32 swi_mload_get_register(u32 addr);
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_put_register: function thinking to write 32 bits registers from supervisor mode
|
||||||
|
|
||||||
|
addr: register address
|
||||||
|
|
||||||
|
val: new value for register
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_put_register(u32 addr, u32 val);
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_set_register: function thinking to set bits to 1 (with OR) in 32 bits registers from supervisor mode
|
||||||
|
|
||||||
|
addr: register address
|
||||||
|
|
||||||
|
val: bits to set must be 1 (operation reg|=val)
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_set_register(u32 addr, u32 val);
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_clr_register: function thinking to clear bits to 0 (with AND) in 32 bits registers from supervisor mode
|
||||||
|
|
||||||
|
addr: register address
|
||||||
|
|
||||||
|
val: bits to clear must be 1 (operation register &=~value)
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_clr_register(u32 addr, u32 val);
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_call_func: call to one function in Supervisor Mode
|
||||||
|
|
||||||
|
in: pointer to data in (received as argument 0 in the function)
|
||||||
|
|
||||||
|
out: pointer to data out (received as argument 0 in the function)
|
||||||
|
|
||||||
|
return: result from the function
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int swi_mload_call_func(int (*func) (void *in, void *out), void *in, void *out);
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_led_on: frontal LED ON
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_led_on(void);
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_led_off: frontal LED OFF
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_led_off(void);
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_led_blink: frontal LED Blinking (note: it use a XOR function, so must call some times for blinking :P). It is thinking to see some activity...
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_led_blink(void);
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_os_software_IRQ_func: function to call from os_software_IRQ(9) in system mode
|
||||||
|
|
||||||
|
system_mode_func: function address
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_os_software_IRQ9_func( int (*system_mode_func)(void));
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_log_func: control the log buffer for os_puts()
|
||||||
|
|
||||||
|
mode: 0-> return log buffer 1-> clear log buffer 2-> set a new log buffer
|
||||||
|
|
||||||
|
buffer_log: new buffer log address (only with mode==2)
|
||||||
|
|
||||||
|
maxsize_log: max size for log (only with mode==2)
|
||||||
|
|
||||||
|
return: current buffer_log (by default 4KB) the string finish with '\0' code
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * swi_mload_log_func(u32 mode, void *buffer_log, int maxsize_log);
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
115
libcios/include/syscalls.h
Normal file
115
libcios/include/syscalls.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#ifndef IOS_SYSCALLS_H
|
||||||
|
#define IOS_SYSCALLS_H
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
typedef struct _ioctlv
|
||||||
|
{
|
||||||
|
void *data;
|
||||||
|
unsigned long len;
|
||||||
|
} ioctlv;
|
||||||
|
typedef struct ipcmessage
|
||||||
|
{
|
||||||
|
unsigned int command; // 0
|
||||||
|
unsigned int result; // 4
|
||||||
|
unsigned int fd; // 8
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
char *device; // 12
|
||||||
|
unsigned int mode; // 16
|
||||||
|
unsigned int resultfd; // 20
|
||||||
|
} open;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
void *data;
|
||||||
|
unsigned int length;
|
||||||
|
} read, write;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
int origin;
|
||||||
|
} seek;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned int command;
|
||||||
|
|
||||||
|
unsigned int *buffer_in;
|
||||||
|
unsigned int length_in;
|
||||||
|
unsigned int *buffer_io;
|
||||||
|
unsigned int length_io;
|
||||||
|
} ioctl;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned int command;
|
||||||
|
|
||||||
|
unsigned int num_in;
|
||||||
|
unsigned int num_io;
|
||||||
|
ioctlv *vector;
|
||||||
|
} ioctlv;
|
||||||
|
};
|
||||||
|
} __attribute__((packed)) ipcmessage;
|
||||||
|
|
||||||
|
// NOTE: I think "autostart" is a flag to indicate an internal (child thread) or external thread
|
||||||
|
int os_thread_create( unsigned int (*entry)(void* arg), void* arg, void* stack, unsigned int stacksize, unsigned int priority, int autostart);
|
||||||
|
void os_thread_set_priority(int id, unsigned int priority);
|
||||||
|
int os_thread_get_priority(void);
|
||||||
|
int os_get_thread_id(void);
|
||||||
|
int os_get_parent_thread_id(void);
|
||||||
|
|
||||||
|
int os_thread_continue(int id);
|
||||||
|
int os_thread_stop(int id);
|
||||||
|
|
||||||
|
int os_message_queue_create(void* ptr, unsigned int max_entries);
|
||||||
|
int os_message_queue_receive(int queue, unsigned int* message, unsigned int flags);
|
||||||
|
int os_message_queue_send(int queue, unsigned int message, int flags);
|
||||||
|
int os_message_queue_send_now(int queue, unsigned int message, int flags);
|
||||||
|
void os_message_queue_ack(void* message, int result);
|
||||||
|
|
||||||
|
int os_heap_create(void* ptr, int size);
|
||||||
|
int os_heap_destroy(int heap);
|
||||||
|
void* os_heap_alloc(int heap, unsigned int size);
|
||||||
|
void* os_heap_alloc_aligned(int heap, int size, int align);
|
||||||
|
void os_heap_free(int heap, void* ptr);
|
||||||
|
int os_device_register(const char* devicename, int queuehandle);
|
||||||
|
|
||||||
|
void os_sync_before_read(void* ptr, int size);
|
||||||
|
void os_sync_after_write(void* ptr, int size);
|
||||||
|
void os_syscall_50(unsigned int unknown);
|
||||||
|
|
||||||
|
int os_open(char* device, int mode);
|
||||||
|
int os_close(int fd);
|
||||||
|
int os_read(int fd, void *d, int len);
|
||||||
|
int os_write(int fd, void *s, int len);
|
||||||
|
int os_seek(int fd, int offset, int mode);
|
||||||
|
int os_ioctlv(int fd, int request, int in, int out, ioctlv *vector);
|
||||||
|
int os_ioctl(int fd, int request, void *in, int bytes_in, void *out, int bytes_out);
|
||||||
|
|
||||||
|
// timer control
|
||||||
|
int os_create_timer(int time_us, int repeat_time_us, int message_queue, int message); // return the timer_id
|
||||||
|
int os_destroy_timer(int time_id);
|
||||||
|
int os_stop_timer(int timer_id);
|
||||||
|
int os_restart_timer(int timer_id, int time_us); // restart one stopped timer
|
||||||
|
int os_timer_now(int time_id);
|
||||||
|
|
||||||
|
#define DEV_EHCI 4
|
||||||
|
int os_register_event_handler(int device, int queue, int message);
|
||||||
|
|
||||||
|
int os_unregister_event_handler(int device);
|
||||||
|
|
||||||
|
int os_software_IRQ(int dev);
|
||||||
|
|
||||||
|
void os_puts(char *str); // to create log in dev/mload
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void debug_printf(const char *fmt, ...);
|
||||||
|
void hexdump(void *d, int len);
|
||||||
|
#else
|
||||||
|
#define debug_printf(a...) do{}while(0)
|
||||||
|
#endif
|
||||||
|
#endif // IOS_SYSCALLS_H
|
144
libcios/include/types.h
Normal file
144
libcios/include/types.h
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#ifndef __GCTYPES_H__
|
||||||
|
#define __GCTYPES_H__
|
||||||
|
|
||||||
|
/*! \file gctypes.h
|
||||||
|
\brief Data type definitions
|
||||||
|
|
||||||
|
*/
|
||||||
|
typedef signed char int8_t ;
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef signed short int16_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef signed int int32_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
typedef unsigned char u8; ///< 8bit unsigned integer
|
||||||
|
typedef unsigned short u16; ///< 16bit unsigned integer
|
||||||
|
typedef unsigned int u32; ///< 32bit unsigned integer
|
||||||
|
typedef unsigned long long u64; ///< 64bit unsigned integer
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
typedef signed char s8; ///< 8bit signed integer
|
||||||
|
typedef signed short s16; ///< 16bit signed integer
|
||||||
|
typedef signed int s32; ///< 32bit signed integer
|
||||||
|
typedef signed long long s64; ///< 64bit signed integer
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
typedef volatile unsigned char vu8; ///< 8bit unsigned volatile integer
|
||||||
|
typedef volatile unsigned short vu16; ///< 16bit unsigned volatile integer
|
||||||
|
typedef volatile unsigned int vu32; ///< 32bit unsigned volatile integer
|
||||||
|
typedef volatile unsigned long long vu64; ///< 64bit unsigned volatile integer
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
typedef volatile signed char vs8; ///< 8bit signed volatile integer
|
||||||
|
typedef volatile signed short vs16; ///< 16bit signed volatile integer
|
||||||
|
typedef volatile signed int vs32; ///< 32bit signed volatile integer
|
||||||
|
typedef volatile signed long long vs64; ///< 64bit signed volatile integer
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
// fixed point math typedefs
|
||||||
|
typedef s16 sfp16; ///< 1:7:8 fixed point
|
||||||
|
typedef s32 sfp32; ///< 1:19:8 fixed point
|
||||||
|
typedef u16 ufp16; ///< 8:8 fixed point
|
||||||
|
typedef u32 ufp32; ///< 24:8 fixed point
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
typedef float f32;
|
||||||
|
typedef double f64;
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
typedef volatile float vf32;
|
||||||
|
typedef volatile double vf64;
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
|
||||||
|
// bool is a standard type in cplusplus, but not in c.
|
||||||
|
#ifndef __cplusplus
|
||||||
|
/** C++ compatible bool for C
|
||||||
|
|
||||||
|
*/
|
||||||
|
typedef u8 bool;
|
||||||
|
enum { false, true };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned int BOOL;
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
// alias type typedefs
|
||||||
|
#define FIXED s32 ///< Alias type for sfp32
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
// boolean defines
|
||||||
|
#ifndef boolean
|
||||||
|
#define boolean u8
|
||||||
|
#endif
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1 ///< True
|
||||||
|
#endif
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0 ///< False
|
||||||
|
#endif
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0 ///< Pointer to 0
|
||||||
|
#endif
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
#ifndef LITTLE_ENDIAN
|
||||||
|
#define LITTLE_ENDIAN 3412
|
||||||
|
#endif /* LITTLE_ENDIAN */
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
#ifndef BIG_ENDIAN
|
||||||
|
#define BIG_ENDIAN 1234
|
||||||
|
#endif /* BIGE_ENDIAN */
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
#ifndef BYTE_ORDER
|
||||||
|
#define BYTE_ORDER BIG_ENDIAN
|
||||||
|
#endif /* BYTE_ORDER */
|
||||||
|
/*+----------------------------------------------------------------------------------------------+*/
|
||||||
|
|
||||||
|
|
||||||
|
//! argv structure
|
||||||
|
/*! \struct __argv
|
||||||
|
|
||||||
|
structure used to set up argc/argv
|
||||||
|
|
||||||
|
*/
|
||||||
|
struct __argv {
|
||||||
|
int argvMagic; //!< argv magic number, set to 0x5f617267 ('_arg') if valid
|
||||||
|
char *commandLine; //!< base address of command line, set of null terminated strings
|
||||||
|
int length;//!< total length of command line
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
char **endARGV;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Default location for the system argv structure.
|
||||||
|
extern struct __argv *__system_argv;
|
||||||
|
|
||||||
|
// argv struct magic number
|
||||||
|
#define ARGV_MAGIC 0x5f617267
|
||||||
|
|
||||||
|
|
||||||
|
typedef uint32_t sec_t;
|
||||||
|
|
||||||
|
/* Attributes */
|
||||||
|
#ifndef ATTRIBUTE_ALIGN
|
||||||
|
# define ATTRIBUTE_ALIGN(v) __attribute__((aligned(v)))
|
||||||
|
#endif
|
||||||
|
#ifndef ATTRIBUTE_PACKED
|
||||||
|
# define ATTRIBUTE_PACKED __attribute__((packed))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Stack align */
|
||||||
|
#define STACK_ALIGN(type, name, cnt, alignment) \
|
||||||
|
u8 _al__##name[((sizeof(type)*(cnt)) + (alignment) + (((sizeof(type)*(cnt))%(alignment)) > 0 ? ((alignment) - ((sizeof(type)*(cnt))%(alignment))) : 0))]; \
|
||||||
|
type *name = (type*)(((u32)(_al__##name)) + ((alignment) - (((u32)(_al__##name))&((alignment)-1))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* TYPES_H */
|
||||||
|
|
||||||
|
|
||||||
|
/* END OF FILE */
|
140
libcios/source/printf.c
Normal file
140
libcios/source/printf.c
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#include "syscalls.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief simple printf like function that write its output to os_puts
|
||||||
|
@param format the format string, followed by format arguments.
|
||||||
|
supported formatters are '%X' '%0*X' '% *X' '%d' '%u'
|
||||||
|
this may not be perfectly compliant with ANSI-C printf, but its suffisant for common debugging..
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void debug_printf(const char *format, ...)
|
||||||
|
{
|
||||||
|
static const char HEX[] = "0123456789ABCDEF";
|
||||||
|
static const char hex[] = "0123456789abcdef";
|
||||||
|
const char *hexp = HEX;
|
||||||
|
int val,i;
|
||||||
|
unsigned int u_val, u_val_inv, base;
|
||||||
|
unsigned char c;
|
||||||
|
va_list list;
|
||||||
|
int zeros = 0,chars;
|
||||||
|
int spaces = 0;
|
||||||
|
char buffer[1024],*ptr;
|
||||||
|
va_start (list, format);
|
||||||
|
|
||||||
|
ptr = buffer;
|
||||||
|
for (;;) {
|
||||||
|
c = *format++;
|
||||||
|
while(c != '%' && c != '\0') // Until '%' or '\0'
|
||||||
|
{
|
||||||
|
*ptr++ = c;
|
||||||
|
c = *format++;
|
||||||
|
}
|
||||||
|
if(c == '\0')
|
||||||
|
{
|
||||||
|
*ptr++ = c;
|
||||||
|
va_end (list);
|
||||||
|
os_puts(buffer);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
hexp = HEX;
|
||||||
|
CONTINUE_FORMAT:
|
||||||
|
switch (c = *format++) {
|
||||||
|
case '0': c = *format++;
|
||||||
|
if(c >= '1' && c <= '9')
|
||||||
|
{
|
||||||
|
zeros = c - '0';
|
||||||
|
goto CONTINUE_FORMAT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
format--;
|
||||||
|
break;
|
||||||
|
case ' ': c = *format++;
|
||||||
|
if(c >= '1' && c <= '9')
|
||||||
|
{
|
||||||
|
spaces = c - '0';
|
||||||
|
goto CONTINUE_FORMAT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
format--;
|
||||||
|
break;
|
||||||
|
case 'c': c = va_arg(list,int);
|
||||||
|
case '%':
|
||||||
|
*ptr++ = c;
|
||||||
|
continue;
|
||||||
|
case 's':
|
||||||
|
if(ptr!=buffer){
|
||||||
|
*ptr=0;
|
||||||
|
os_puts(buffer);
|
||||||
|
}
|
||||||
|
os_puts(va_arg(list,char*));
|
||||||
|
ptr=buffer;
|
||||||
|
break;
|
||||||
|
case '\0':
|
||||||
|
default: format--; continue; // will write it at next loop..
|
||||||
|
case 'u':
|
||||||
|
case 'd': base = 10; goto CONVERT_THIS;
|
||||||
|
case 'p': zeros = 8;case 'x' : hexp = hex;
|
||||||
|
case 'X':base = 16;
|
||||||
|
|
||||||
|
CONVERT_THIS:
|
||||||
|
val = va_arg(list,int);
|
||||||
|
if (c == 'd') {
|
||||||
|
if (val < 0) {
|
||||||
|
val = - val;
|
||||||
|
c = '-';
|
||||||
|
*ptr++ = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
u_val = val;
|
||||||
|
u_val_inv = 0;
|
||||||
|
chars = 0;
|
||||||
|
while(u_val){u_val_inv*= base;u_val_inv += u_val %base;u_val/=base; chars++;}
|
||||||
|
if(chars == 0)chars++;
|
||||||
|
|
||||||
|
if(zeros){
|
||||||
|
for(i=zeros - chars;i>0;i--)
|
||||||
|
*ptr++ = '0';
|
||||||
|
}
|
||||||
|
if(spaces)
|
||||||
|
{
|
||||||
|
for(i=spaces - chars;i>0;i--)
|
||||||
|
*ptr++ = ' ';
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
c = u_val_inv % base;
|
||||||
|
*ptr++ = hexp[c];
|
||||||
|
u_val_inv /= base;
|
||||||
|
chars --;
|
||||||
|
} while (chars>0);
|
||||||
|
zeros = 0;
|
||||||
|
spaces = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char ascii(char s) {
|
||||||
|
if(s < 0x20) return '.';
|
||||||
|
if(s > 0x7E) return '.';
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hexdump(void *d, int len) {
|
||||||
|
u8 *data;
|
||||||
|
int i, off;
|
||||||
|
data = (u8*)d;
|
||||||
|
for (off=0; off<len; off += 16) {
|
||||||
|
debug_printf("%08x ",off);
|
||||||
|
for(i=0; i<16; i++)
|
||||||
|
if((i+off)>=len) debug_printf(" ");
|
||||||
|
else debug_printf("%02x ",data[off+i]);
|
||||||
|
|
||||||
|
debug_printf(" ");
|
||||||
|
for(i=0; i<16; i++)
|
||||||
|
if((i+off)>=len) debug_printf(" ");
|
||||||
|
else debug_printf("%c",ascii(data[off+i]));
|
||||||
|
debug_printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
269
libcios/source/swi_mload.c
Normal file
269
libcios/source/swi_mload.c
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
/* SWI service from dev/mload (c) 2009 Hermes / www.elotrolado.net */
|
||||||
|
|
||||||
|
#include "swi_mload.h"
|
||||||
|
|
||||||
|
// ASM function
|
||||||
|
extern int swi_mload_func (u32 arg0, u32 arg1, u32 arg2, u32 arg3);
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_add_handler: add a new service handler for SWI
|
||||||
|
|
||||||
|
svc_code: for example 0xab for svc 0xab
|
||||||
|
|
||||||
|
func: function for the new SWI service
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_add_handler(u8 svc_code, int (*func) (u32 arg0, u32 arg1, u32 arg2, u32 arg3))
|
||||||
|
{
|
||||||
|
swi_mload_func(0, (u32) svc_code, (u32) func, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_EHCI_data: gets the EHCI struct from dev/mload
|
||||||
|
|
||||||
|
return: the struct pointer
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * swi_mload_EHCI_data(void)
|
||||||
|
{
|
||||||
|
return (void *) swi_mload_func(1, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_get_syscall_base: gets the syscall base address to call directly
|
||||||
|
|
||||||
|
return: the address
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
u32 swi_mload_get_syscall_base(void)
|
||||||
|
{
|
||||||
|
return (u32) swi_mload_func(17, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_get_ios_base: gets the ios base (FFS, ES, IOSP) used to create this cIOS
|
||||||
|
|
||||||
|
return: the address
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
u32 swi_mload_get_ios_base(void)
|
||||||
|
{
|
||||||
|
return (u32) swi_mload_func(18, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_memcpy: memcpy from supervisor mode
|
||||||
|
|
||||||
|
dst: destination address
|
||||||
|
|
||||||
|
src: source address
|
||||||
|
|
||||||
|
len: datas to move
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_memcpy(void * dst, void * src, int len)
|
||||||
|
{
|
||||||
|
if(len<=0) return;
|
||||||
|
swi_mload_func(2, (u32) dst, (u32) src, (u32) len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_memcpy_from_uncached: memcpy from supervisor mode. Copies from uncached source RAM to cached RAM
|
||||||
|
|
||||||
|
dst: destination address
|
||||||
|
|
||||||
|
src: source address
|
||||||
|
|
||||||
|
len: datas to move
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_memcpy_from_uncached(void * dst, void * src, int len)
|
||||||
|
{
|
||||||
|
if(len<=0) return;
|
||||||
|
swi_mload_func(9, (u32) dst, (u32) src, (u32) len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_get_register: function thinking to read 32 bits registers from supervisor mode
|
||||||
|
|
||||||
|
addr: register address
|
||||||
|
|
||||||
|
return: value
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
u32 swi_mload_get_register(u32 addr)
|
||||||
|
{
|
||||||
|
return swi_mload_func(3, (u32) addr, (u32) 0, (u32) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_put_register: function thinking to write 32 bits registers from supervisor mode
|
||||||
|
|
||||||
|
addr: register address
|
||||||
|
|
||||||
|
val: new value for register
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_put_register(u32 addr, u32 val)
|
||||||
|
{
|
||||||
|
swi_mload_func(4, (u32) addr, (u32) val, (u32) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_set_register: function thinking to set bits to 1 (with OR) in 32 bits registers from supervisor mode
|
||||||
|
|
||||||
|
addr: register address
|
||||||
|
|
||||||
|
val: bits to set must be 1 (operation reg|=val)
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_set_register(u32 addr, u32 val)
|
||||||
|
{
|
||||||
|
swi_mload_func(5, (u32) addr, (u32) val, (u32) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_clr_register: function thinking to clear bits to 0 (with AND) in 32 bits registers from supervisor mode
|
||||||
|
|
||||||
|
addr: register address
|
||||||
|
|
||||||
|
val: bits to clear must be 1 (operation register &=~value)
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_clr_register(u32 addr, u32 val)
|
||||||
|
{
|
||||||
|
swi_mload_func(6, (u32) addr, (u32) val, (u32) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_call_func: call to one function in Supervisor Mode
|
||||||
|
|
||||||
|
in: pointer to data in (received as argument 0 in the function)
|
||||||
|
|
||||||
|
out: pointer to data out (received as argument 0 in the function)
|
||||||
|
|
||||||
|
return: result from the function
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int swi_mload_call_func(int (*func) (void *in, void *out), void *in, void *out)
|
||||||
|
{
|
||||||
|
return swi_mload_func(16, (u32) func, (u32) in, (u32) out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_led_on: frontal LED ON
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_led_on(void)
|
||||||
|
{
|
||||||
|
swi_mload_func(128, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_led_off: frontal LED OFF
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_led_off(void)
|
||||||
|
{
|
||||||
|
swi_mload_func(129, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_led_blink: frontal LED Blinking (note: it use a XOR function, so must call some times for blinking :P). It is thinking to see some activity...
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_led_blink(void)
|
||||||
|
{
|
||||||
|
swi_mload_func(130, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_os_software_IRQ_func: function to call from os_software_IRQ(9) in system mode
|
||||||
|
|
||||||
|
system_mode_func: function address
|
||||||
|
|
||||||
|
return: none
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void swi_mload_os_software_IRQ9_func( int (*system_mode_func)(void))
|
||||||
|
{
|
||||||
|
swi_mload_func(7, (u32) system_mode_func, (u32) 0, (u32) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
swi_mload_log_func: control the log buffer for os_puts()
|
||||||
|
|
||||||
|
mode: 0-> return log buffer 1-> clear log buffer 2-> set a new log buffer
|
||||||
|
|
||||||
|
buffer_log: new buffer log address (only with mode==2)
|
||||||
|
|
||||||
|
maxsize_log: max size for log (only with mode==2)
|
||||||
|
|
||||||
|
return: current buffer_log (by default 4KB) the string finish with '\0' code
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * swi_mload_log_func(u32 mode, void *buffer_log, int maxsize_log)
|
||||||
|
{
|
||||||
|
return (void *) swi_mload_func(8, (u32) mode, (u32) buffer_log, (u32) maxsize_log);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************************************************************************/
|
||||||
|
|
||||||
|
|
13
libcios/source/swi_mload.s
Normal file
13
libcios/source/swi_mload.s
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* SWI service from dev/mload (c) 2009 Hermes / www.elotrolado.net */
|
||||||
|
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.arm
|
||||||
|
.code 32
|
||||||
|
.global swi_mload_func
|
||||||
|
swi_mload_func:
|
||||||
|
|
||||||
|
svc 0xcc
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
|
258
libcios/source/syscalls.s
Normal file
258
libcios/source/syscalls.s
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
/* syscalls.s (c) 2009, Hermes
|
||||||
|
info from http://wiibrew.org/wiki/IOS/Syscalls
|
||||||
|
*/
|
||||||
|
|
||||||
|
.macro syscall vec_sys
|
||||||
|
.long 0xE6000010 +(\vec_sys<<5)
|
||||||
|
bx lr
|
||||||
|
.endm
|
||||||
|
.align 4
|
||||||
|
.arm
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_thread_create
|
||||||
|
os_thread_create:
|
||||||
|
syscall 0x0
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_thread_joint
|
||||||
|
os_thread_joint:
|
||||||
|
syscall 0x1
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_thread_cancel
|
||||||
|
os_thread_cancel:
|
||||||
|
syscall 0x2
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_get_thread_id
|
||||||
|
os_get_thread_id:
|
||||||
|
syscall 0x3
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_get_parent_thread_id
|
||||||
|
os_get_parent_thread_id:
|
||||||
|
syscall 0x4
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_thread_continue
|
||||||
|
os_thread_continue:
|
||||||
|
syscall 0x5
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_thread_stop
|
||||||
|
os_thread_stop:
|
||||||
|
syscall 0x6
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_thread_yield
|
||||||
|
os_thread_yiel:
|
||||||
|
syscall 0x7
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_thread_get_priority
|
||||||
|
os_thread_get_priority :
|
||||||
|
syscall 0x8
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_thread_set_priority
|
||||||
|
os_thread_set_priority:
|
||||||
|
syscall 0x9
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_message_queue_create
|
||||||
|
os_message_queue_create:
|
||||||
|
syscall 0xa
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_message_queue_destroy
|
||||||
|
os_message_queue_destroy:
|
||||||
|
syscall 0xb
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_message_queue_send
|
||||||
|
os_message_queue_send:
|
||||||
|
syscall 0xc
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_message_queue_send_now
|
||||||
|
os_message_queue_send_now:
|
||||||
|
syscall 0xd
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_message_queue_receive
|
||||||
|
os_message_queue_receive:
|
||||||
|
syscall 0xe
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_register_event_handler
|
||||||
|
os_register_event_handler:
|
||||||
|
syscall 0xf
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_unregister_event_handler
|
||||||
|
os_unregister_event_handler:
|
||||||
|
syscall 0x10
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_create_timer
|
||||||
|
os_create_timer:
|
||||||
|
syscall 0x11
|
||||||
|
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_restart_timer
|
||||||
|
os_restart_timer:
|
||||||
|
syscall 0x12
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_stop_timer
|
||||||
|
os_stop_timer:
|
||||||
|
syscall 0x13
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_destroy_timer
|
||||||
|
os_destroy_timer:
|
||||||
|
syscall 0x14
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_timer_now
|
||||||
|
os_timer_now:
|
||||||
|
syscall 0x15
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_heap_create
|
||||||
|
os_heap_create:
|
||||||
|
syscall 0x16
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_heap_destroy
|
||||||
|
os_heap_destroy:
|
||||||
|
syscall 0x17
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_heap_alloc
|
||||||
|
os_heap_alloc:
|
||||||
|
syscall 0x18
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_heap_alloc_aligned
|
||||||
|
os_heap_alloc_aligned:
|
||||||
|
syscall 0x19
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_heap_free
|
||||||
|
os_heap_free:
|
||||||
|
syscall 0x1a
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_device_register
|
||||||
|
os_device_register:
|
||||||
|
syscall 0x1b
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_open
|
||||||
|
os_open:
|
||||||
|
syscall 0x1c
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_close
|
||||||
|
os_close:
|
||||||
|
syscall 0x1d
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_read
|
||||||
|
os_read:
|
||||||
|
syscall 0x1e
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_write
|
||||||
|
os_write:
|
||||||
|
syscall 0x1f
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_seek
|
||||||
|
os_seek:
|
||||||
|
syscall 0x20
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_ioctl
|
||||||
|
os_ioctl:
|
||||||
|
syscall 0x21
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_ioctlv
|
||||||
|
os_ioctlv:
|
||||||
|
syscall 0x22
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_open_async
|
||||||
|
os_open_async:
|
||||||
|
syscall 0x23
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_close_async
|
||||||
|
os_close_async:
|
||||||
|
syscall 0x24
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_read_async
|
||||||
|
os_read_async:
|
||||||
|
syscall 0x25
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_write_async
|
||||||
|
os_write_async:
|
||||||
|
syscall 0x26
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_seek_async
|
||||||
|
os_seek_async:
|
||||||
|
syscall 0x27
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_ioctl_async
|
||||||
|
os_ioctl_async:
|
||||||
|
syscall 0x28
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_ioctlv_async
|
||||||
|
os_ioctlv_async:
|
||||||
|
syscall 0x29
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_message_queue_ack
|
||||||
|
os_message_queue_ack:
|
||||||
|
syscall 0x2a
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_software_IRQ
|
||||||
|
os_software_IRQ:
|
||||||
|
syscall 0x34
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_sync_before_read
|
||||||
|
os_sync_before_read:
|
||||||
|
syscall 0x3f
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_sync_after_write
|
||||||
|
os_sync_after_write:
|
||||||
|
syscall 0x40
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_syscall_50
|
||||||
|
os_syscall_50:
|
||||||
|
syscall 0x50
|
||||||
|
|
||||||
|
.code 32
|
||||||
|
.global os_puts
|
||||||
|
os_puts:
|
||||||
|
adds r1,r0,#0
|
||||||
|
movs R0,#4
|
||||||
|
svc 0xAB
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
4
mload/MakeIt.bat
Normal file
4
mload/MakeIt.bat
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
make
|
||||||
|
|
||||||
|
pause
|
143
mload/Makefile
Normal file
143
mload/Makefile
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# Clear the implicit built in rules
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# 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 := $(notdir $(CURDIR))
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := source ../libcios/source
|
||||||
|
DATA := data
|
||||||
|
INCLUDES := include ../tinyehci ../libcios/include
|
||||||
|
SCRIPTDIR := scripts
|
||||||
|
BIN := bin
|
||||||
|
|
||||||
|
STRIPIOS := ../stripios/stripios.exe
|
||||||
|
|
||||||
|
LIBS :=
|
||||||
|
LIBDIRS :=
|
||||||
|
|
||||||
|
export IOS_MODULE=haxx
|
||||||
|
|
||||||
|
CFLAGS+=-D$(IOS_MODULE)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# the prefix on the compiler executables
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
PREFIX := $(DEVKITARM)/bin/arm-eabi-
|
||||||
|
CC := $(PREFIX)gcc
|
||||||
|
CXX := $(PREFIX)g++
|
||||||
|
AR := $(PREFIX)ar
|
||||||
|
OBJCOPY := $(PREFIX)objcopy
|
||||||
|
LD := $(PREFIX)g++
|
||||||
|
AS := $(PREFIX)g++
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# linker script
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LINKSCRIPT := $(ROOT)/$(SCRIPTDIR)/link.ld
|
||||||
|
SPECS := $(ROOT)/$(SCRIPTDIR)/nostart.specs
|
||||||
|
|
||||||
|
ifeq ($(BUILDING),$(emptystring))
|
||||||
|
|
||||||
|
export ROOT := $(CURDIR)
|
||||||
|
|
||||||
|
|
||||||
|
all:
|
||||||
|
@[ -d $(BUILD) ] || mkdir -p $(BUILD)
|
||||||
|
@$(MAKE) -C $(BUILD) --no-print-directory -f $(CURDIR)/Makefile BUILDING=all
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(BIN)/*.elf
|
||||||
|
else
|
||||||
|
|
||||||
|
TARGET := $(notdir $(ROOT))
|
||||||
|
STRIPIOS := $(ROOT)/$(STRIPIOS)
|
||||||
|
#----------------------------------------------------
|
||||||
|
# MS Visual Studio Style Fix:
|
||||||
|
#----------------------------------------------------
|
||||||
|
STYLEFIX = 2>&1 | sed -e 's/\([a-zA-Z\.]\+\):\([0-9]\+\):\([0-9]\+:\)\?\(.\+\)/\1(\2):\4/' -e 's/undefined/error: undefined/'
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# automatically build a list of object files for our project
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
OUTPUT := $(ROOT)/$(BIN)/$(TARGET)
|
||||||
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.c)))
|
||||||
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.cpp)))
|
||||||
|
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.s)))
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.S)))
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(ROOT)/$(dir)/*.*)))
|
||||||
|
|
||||||
|
OFILES := $(addsuffix _bin.o,$(BINFILES)) \
|
||||||
|
$(CPPFILES:.cpp=_cpp.o) $(CFILES:.c=_c.o) \
|
||||||
|
$(sFILES:.s=_s.o) $(SFILES:.S=_S.o)
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
VPATH = $(foreach dir,$(SOURCES),$(ROOT)/$(dir))
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
INCLUDE := $(foreach dir,$(INCLUDES),-I$(ROOT)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(ROOT)/$(BUILD)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# build a list of library paths
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||||
|
|
||||||
|
ARCH = -mcpu=arm9tdmi -mtune=arm9tdmi -mthumb -mthumb-interwork -mbig-endian
|
||||||
|
|
||||||
|
CFLAGS = -g $(ARCH) $(INCLUDE) -fno-strict-aliasing -Wall -O3 -fomit-frame-pointer -ffast-math -fverbose-asm -Wpointer-arith -Winline -Wundef -g -ffunction-sections -fdata-sections -fno-exceptions
|
||||||
|
CFLAGS += -Wstrict-prototypes
|
||||||
|
|
||||||
|
|
||||||
|
AFLAGS = -g $(ARCH) -x assembler-with-cpp
|
||||||
|
|
||||||
|
LDFLAGS = -g $(ARCH) -specs=$(SPECS) -T$(LINKSCRIPT) $(LIBPATHS) $(LIBS) -Wl,--gc-sections -Wl,-static -Wl,-Map,$(TARGET).map -nostartfiles
|
||||||
|
|
||||||
|
|
||||||
|
$(OUTPUT).elf: $(TARGET).elf
|
||||||
|
@echo stripping $(notdir $@)
|
||||||
|
@$(STRIPIOS) $< $@ strip 0x13700000
|
||||||
|
cp -f $(OUTPUT).elf ../../cios_installer/data/$(TARGET).elf
|
||||||
|
|
||||||
|
|
||||||
|
%.elf: $(OFILES)
|
||||||
|
@echo linking $(notdir $@)
|
||||||
|
@$(LD) -g -o $@ $(OFILES) $(LDFLAGS) $(STYLEFIX)
|
||||||
|
|
||||||
|
|
||||||
|
%_cpp.o : %.cpp
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(CXX) -MMD -MF $*_cpp.d $(CFLAGS) -c $< -o$@ $(STYLEFIX)
|
||||||
|
|
||||||
|
%_c.o : %.c
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(CC) -MMD -MF $*_c.d $(CFLAGS) -c $< -o$@ $(STYLEFIX)
|
||||||
|
|
||||||
|
%_s.o : %.s
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(AS) -MMD -MF $*_s.d $(AFLAGS) -c $< -o$@ $(STYLEFIX)
|
||||||
|
|
||||||
|
%_bin.o : %.bin
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
define bin2o
|
||||||
|
@echo -e "\t.section .rodata\n\t.align 4\n\t.global $(*)\n\t.global $(*)_end\n$(*):\n\t.incbin \"$(subst /,\\\\\\\\,$(shell echo $< | sed 's=/==;s=/=:/='))\"\n$(*)_end:\n" > $@.s
|
||||||
|
@$(CC) $(ASFLAGS) $(AFLAGS) -c $@.s -o $@
|
||||||
|
@rm -rf $@.s
|
||||||
|
endef
|
||||||
|
|
||||||
|
endif
|
143
mload/Makefile_port1
Normal file
143
mload/Makefile_port1
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# Clear the implicit built in rules
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# 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 := $(notdir $(CURDIR))
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := source ../libcios/source
|
||||||
|
DATA := data
|
||||||
|
INCLUDES := include ../tinyehci ../libcios/include
|
||||||
|
SCRIPTDIR := scripts
|
||||||
|
BIN := bin
|
||||||
|
|
||||||
|
STRIPIOS := ../stripios/stripios.exe
|
||||||
|
|
||||||
|
LIBS :=
|
||||||
|
LIBDIRS :=
|
||||||
|
|
||||||
|
export IOS_MODULE=haxx
|
||||||
|
|
||||||
|
CFLAGS+=-D$(IOS_MODULE)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# the prefix on the compiler executables
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
PREFIX := $(DEVKITARM)/bin/arm-eabi-
|
||||||
|
CC := $(PREFIX)gcc
|
||||||
|
CXX := $(PREFIX)g++
|
||||||
|
AR := $(PREFIX)ar
|
||||||
|
OBJCOPY := $(PREFIX)objcopy
|
||||||
|
LD := $(PREFIX)g++
|
||||||
|
AS := $(PREFIX)g++
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# linker script
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LINKSCRIPT := $(ROOT)/$(SCRIPTDIR)/link.ld
|
||||||
|
SPECS := $(ROOT)/$(SCRIPTDIR)/nostart.specs
|
||||||
|
|
||||||
|
ifeq ($(BUILDING),$(emptystring))
|
||||||
|
|
||||||
|
export ROOT := $(CURDIR)
|
||||||
|
|
||||||
|
|
||||||
|
all:
|
||||||
|
@[ -d $(BUILD) ] || mkdir -p $(BUILD)
|
||||||
|
@$(MAKE) -C $(BUILD) --no-print-directory -f $(CURDIR)/Makefile BUILDING=all
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(BIN)/*.elf
|
||||||
|
else
|
||||||
|
|
||||||
|
TARGET := $(notdir $(ROOT))
|
||||||
|
STRIPIOS := $(ROOT)/$(STRIPIOS)
|
||||||
|
#----------------------------------------------------
|
||||||
|
# MS Visual Studio Style Fix:
|
||||||
|
#----------------------------------------------------
|
||||||
|
STYLEFIX = 2>&1 | sed -e 's/\([a-zA-Z\.]\+\):\([0-9]\+\):\([0-9]\+:\)\?\(.\+\)/\1(\2):\4/' -e 's/undefined/error: undefined/'
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# automatically build a list of object files for our project
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
OUTPUT := $(ROOT)/$(BIN)/$(TARGET)
|
||||||
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.c)))
|
||||||
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.cpp)))
|
||||||
|
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.s)))
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.S)))
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(ROOT)/$(dir)/*.*)))
|
||||||
|
|
||||||
|
OFILES := $(addsuffix _bin.o,$(BINFILES)) \
|
||||||
|
$(CPPFILES:.cpp=_cpp.o) $(CFILES:.c=_c.o) \
|
||||||
|
$(sFILES:.s=_s.o) $(SFILES:.S=_S.o)
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
VPATH = $(foreach dir,$(SOURCES),$(ROOT)/$(dir))
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
INCLUDE := $(foreach dir,$(INCLUDES),-I$(ROOT)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(ROOT)/$(BUILD)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# build a list of library paths
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||||
|
|
||||||
|
ARCH = -mcpu=arm9tdmi -mtune=arm9tdmi -mthumb -mthumb-interwork -mbig-endian
|
||||||
|
|
||||||
|
CFLAGS = -DUSE_USB_PORT_1 -g $(ARCH) $(INCLUDE) -fno-strict-aliasing -Wall -O3 -fomit-frame-pointer -ffast-math -fverbose-asm -Wpointer-arith -Winline -Wundef -g -ffunction-sections -fdata-sections -fno-exceptions
|
||||||
|
CFLAGS += -Wstrict-prototypes
|
||||||
|
|
||||||
|
|
||||||
|
AFLAGS = -g $(ARCH) -x assembler-with-cpp
|
||||||
|
|
||||||
|
LDFLAGS = -g $(ARCH) -specs=$(SPECS) -T$(LINKSCRIPT) $(LIBPATHS) $(LIBS) -Wl,--gc-sections -Wl,-static -Wl,-Map,$(TARGET).map -nostartfiles
|
||||||
|
|
||||||
|
|
||||||
|
$(OUTPUT).elf: $(TARGET).elf
|
||||||
|
@echo stripping $(notdir $@)
|
||||||
|
@$(STRIPIOS) $< $@ strip 0x13700000
|
||||||
|
cp -f $(OUTPUT).elf ../../cios_installer/data/$(TARGET).elf
|
||||||
|
|
||||||
|
|
||||||
|
%.elf: $(OFILES)
|
||||||
|
@echo linking $(notdir $@)
|
||||||
|
@$(LD) -g -o $@ $(OFILES) $(LDFLAGS) $(STYLEFIX)
|
||||||
|
|
||||||
|
|
||||||
|
%_cpp.o : %.cpp
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(CXX) -MMD -MF $*_cpp.d $(CFLAGS) -c $< -o$@ $(STYLEFIX)
|
||||||
|
|
||||||
|
%_c.o : %.c
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(CC) -MMD -MF $*_c.d $(CFLAGS) -c $< -o$@ $(STYLEFIX)
|
||||||
|
|
||||||
|
%_s.o : %.s
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(AS) -MMD -MF $*_s.d $(AFLAGS) -c $< -o$@ $(STYLEFIX)
|
||||||
|
|
||||||
|
%_bin.o : %.bin
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
define bin2o
|
||||||
|
@echo -e "\t.section .rodata\n\t.align 4\n\t.global $(*)\n\t.global $(*)_end\n$(*):\n\t.incbin \"$(subst /,\\\\\\\\,$(shell echo $< | sed 's=/==;s=/=:/='))\"\n$(*)_end:\n" > $@.s
|
||||||
|
@$(CC) $(ASFLAGS) $(AFLAGS) -c $@.s -o $@
|
||||||
|
@rm -rf $@.s
|
||||||
|
endef
|
||||||
|
|
||||||
|
endif
|
9
mload/include/utils.h
Normal file
9
mload/include/utils.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#define swab32(x) ((u32)( \
|
||||||
|
(((u32)(x) & (u32)0x000000ffUL) << 24) | \
|
||||||
|
(((u32)(x) & (u32)0x0000ff00UL) << 8) | \
|
||||||
|
(((u32)(x) & (u32)0x00ff0000UL) >> 8) | \
|
||||||
|
(((u32)(x) & (u32)0xff000000UL) >> 24)))
|
||||||
|
#define swab16(x) ((u16)( \
|
||||||
|
(((u16)(x) & (u16)0x00ffU) << 8) | \
|
||||||
|
(((u16)(x) & (u16)0xff00U) >> 8)))
|
||||||
|
|
63
mload/scripts/link.ld
Normal file
63
mload/scripts/link.ld
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
OUTPUT_FORMAT("elf32-bigarm", "elf32-bigarm", "elf32-littlearm")
|
||||||
|
OUTPUT_ARCH(arm)
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Change exe start and ram start as needed for the custom IOS module.
|
||||||
|
Current settings are for the freespace after OH1 module from IOS 31.
|
||||||
|
*/
|
||||||
|
|
||||||
|
MEMORY {
|
||||||
|
ios_info_table : ORIGIN = 0x0, LENGTH = 0xf4
|
||||||
|
exe(rwx) : ORIGIN = 0x138c0000, LENGTH = 0x4000
|
||||||
|
|
||||||
|
ram(rw) : ORIGIN = 0x138c8000, LENGTH = 0x8000
|
||||||
|
|
||||||
|
ios_exe(rw) : ORIGIN = 0x13700000, LENGTH = 0x80000
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
__exe_start_virt__ = 0x138c0000;
|
||||||
|
__exe_start_phys__ = 0x138c0000;
|
||||||
|
__ram_start_virt__ = 0x138c8000;
|
||||||
|
__ram_start_phys__ = 0x138c8000;
|
||||||
|
__ios_info_table_start = 0x0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } .debug_info 0 : { *(.debug_info) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } .note.arm.ident 0 : { KEEP (*(.note.arm.ident)) }
|
||||||
|
|
||||||
|
|
||||||
|
.mem_exe 0x13700000 : {
|
||||||
|
*(.mem_exe)
|
||||||
|
} > ios_exe
|
||||||
|
|
||||||
|
|
||||||
|
.ios_info_table __ios_info_table_start : { . = .; KEEP (*(.ios_info_table)) } > ios_info_table
|
||||||
|
.init __exe_start_virt__ : AT (__exe_start_phys__) { . = .; KEEP (*(.init)) } > exe
|
||||||
|
.text ALIGN (0x4) : {
|
||||||
|
*(.text*)
|
||||||
|
*(.gnu.warning)
|
||||||
|
*(.gnu.linkonce.t.*)
|
||||||
|
*(.init)
|
||||||
|
*(.glue_7)
|
||||||
|
*(.glue_7t) } > exe
|
||||||
|
.data __ram_start_virt__ : AT (__ram_start_phys__) { KEEP( *(.ios_data) ) *(.data*) *(.data1) *(.gnu.linkonce.d.*) . = ALIGN (4); __CTOR_LIST__ = ABSOLUTE (.); KEEP (*(SORT (.ctors*))) __CTOR_END__ = ABSOLUTE (.); __DTOR_LIST__ = ABSOLUTE (.); KEEP (*(SORT (.dtors*))) __DTOR_END__ = ABSOLUTE (.); *(.dynamic) *(.sdata*) *(.gnu.linkonce.s.*) . = ALIGN (4); *(.2ram.*) } > ram
|
||||||
|
.fini : { . = .; *(.fini) } > ram
|
||||||
|
.rodata ALIGN (0x4) : {
|
||||||
|
. = .;
|
||||||
|
*(.rodata*)
|
||||||
|
*(.gnu.linkonce.r.*) } > ram
|
||||||
|
.rodata1 ALIGN (0x4) : { . = .; *(.rodata1) } > ram
|
||||||
|
.fixup ALIGN (0x4) : { . = .; *(.fixup) } > ram
|
||||||
|
.gcc_except_table ALIGN (0x4) : { . = .; *(.gcc_except_table) } > ram
|
||||||
|
.got ALIGN (0x4) : { *(.got.plt) *(.got) } > ram
|
||||||
|
.bss ALIGN (0x4) : { *(.scommon) *(.dynsbss) *(.sbss*) *(.gnu.linkonce.sb.*) *(.dynbss) *(.bss*) *(.gnu.linkonce.b.*) *(COMMON) KEEP( *(.ios_bss) ) } > ram
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
}
|
2
mload/scripts/nostart.specs
Normal file
2
mload/scripts/nostart.specs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*startfile:
|
||||||
|
crti%O%s crtbegin%O%s
|
299
mload/source/crt0.s
Normal file
299
mload/source/crt0.s
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
/*
|
||||||
|
Custom IOS module for Wii.
|
||||||
|
Copyright (C) 2008 neimod.
|
||||||
|
|
||||||
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section ".init"
|
||||||
|
.global _start
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.arm
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* crt0.s - IOS module startup code
|
||||||
|
*
|
||||||
|
*******************************************************************************
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* v1.0 - 26 July 2008 - initial release by neimod
|
||||||
|
* v1.1 - 5 September 2008 - prepared for public release
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// DIP values
|
||||||
|
//.EQU ios_thread_arg, 3
|
||||||
|
//.EQU ios_thread_priority, 0x54
|
||||||
|
// OH0 values
|
||||||
|
.EQU ios_thread_arg, 4
|
||||||
|
.EQU ios_thread_priority, 0x79
|
||||||
|
.EQU ios_thread_stacksize, 0x1000
|
||||||
|
|
||||||
|
// WARNING: You cannot change this code !!!!
|
||||||
|
_start:
|
||||||
|
b _start_2
|
||||||
|
|
||||||
|
|
||||||
|
.global table_jump_ext
|
||||||
|
.thumb_func
|
||||||
|
table_jump_ext:
|
||||||
|
.code 16
|
||||||
|
.align 2
|
||||||
|
b ES_ioctlv_ret__
|
||||||
|
nop
|
||||||
|
b IRQ_9
|
||||||
|
nop
|
||||||
|
.code 32
|
||||||
|
b swi_vector
|
||||||
|
|
||||||
|
|
||||||
|
.global ES_ioctlv_ret__
|
||||||
|
.thumb_func
|
||||||
|
ES_ioctlv_ret__:
|
||||||
|
.code 16
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
ldr r1, = ES_ioctlv_vect
|
||||||
|
ldr r1, [r1]
|
||||||
|
nop
|
||||||
|
cmp r1, #0
|
||||||
|
beq ES_ioctlv_ret
|
||||||
|
bx r1
|
||||||
|
|
||||||
|
/* return to dev/es ioctlv routine */
|
||||||
|
|
||||||
|
.global ES_ioctlv_ret
|
||||||
|
.thumb_func
|
||||||
|
.code 16
|
||||||
|
ES_ioctlv_ret:
|
||||||
|
push {r4-r6,lr}
|
||||||
|
sub sp, sp, #0x20
|
||||||
|
ldr r5, [r0,#8]
|
||||||
|
add r1, r0, #0
|
||||||
|
ldr r3, = 0x201000D5
|
||||||
|
bx r3
|
||||||
|
|
||||||
|
// to call one far function in system mode using os_software_IRQ(9)
|
||||||
|
.code 16
|
||||||
|
.global IRQ_9
|
||||||
|
.thumb_func
|
||||||
|
IRQ_9:
|
||||||
|
|
||||||
|
push {r6}
|
||||||
|
bl call_system
|
||||||
|
add r5, r0, #0
|
||||||
|
pop {r6}
|
||||||
|
|
||||||
|
irq9_1:
|
||||||
|
bl exit_irq9
|
||||||
|
add r0, r5, #0
|
||||||
|
|
||||||
|
pop {r4-r6}
|
||||||
|
pop {r1}
|
||||||
|
bx r1
|
||||||
|
|
||||||
|
|
||||||
|
.code 16
|
||||||
|
exit_irq9:
|
||||||
|
.thumb_func
|
||||||
|
bx pc
|
||||||
|
.align 4
|
||||||
|
.code 32
|
||||||
|
|
||||||
|
add r0, r6, #0
|
||||||
|
mrs r1, cpsr
|
||||||
|
bic r1, r1, #0xc0
|
||||||
|
orr r1, r1, r0
|
||||||
|
msr cpsr_c, r1
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
// END of critic area
|
||||||
|
.align 4
|
||||||
|
.code 32
|
||||||
|
_start_2:
|
||||||
|
|
||||||
|
ldr sp, =ios_thread_stack
|
||||||
|
|
||||||
|
/* Execute main program */
|
||||||
|
mov r0, #0 @ int argc
|
||||||
|
mov r1, #0 @ char *argv[]
|
||||||
|
ldr r3, =main
|
||||||
|
bx r3
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.code 32
|
||||||
|
.global direct_syscall
|
||||||
|
direct_syscall:
|
||||||
|
ldr r12, =syscall_base
|
||||||
|
ldr r12, [r12]
|
||||||
|
nop
|
||||||
|
ldr r12, [r12,r11,lsl#2]
|
||||||
|
nop
|
||||||
|
bx r12
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.code 32
|
||||||
|
.global direct_os_sync_before_read
|
||||||
|
direct_os_sync_before_read:
|
||||||
|
|
||||||
|
|
||||||
|
mov r11, #0x3f
|
||||||
|
b direct_syscall
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.code 32
|
||||||
|
.global direct_os_sync_after_write
|
||||||
|
direct_os_sync_after_write:
|
||||||
|
|
||||||
|
|
||||||
|
mov r11, #0x40
|
||||||
|
b direct_syscall
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.code 32
|
||||||
|
.global read_access_perm
|
||||||
|
read_access_perm:
|
||||||
|
mrc p15, 0, r0,c3,c0
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.code 32
|
||||||
|
.global write_access_perm
|
||||||
|
write_access_perm:
|
||||||
|
mcr p15, 0, r0,c3,c0
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.code 32
|
||||||
|
.global ic_invalidate
|
||||||
|
ic_invalidate:
|
||||||
|
mov r0, #0
|
||||||
|
mcr p15, 0, r0, c7, c5, 0
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
// to exit in system mode using os_software_IRQ(10)
|
||||||
|
.global swi_vector
|
||||||
|
.code 16
|
||||||
|
swi_vector:
|
||||||
|
bx pc
|
||||||
|
.code 32
|
||||||
|
ldr sp, =swi_stack
|
||||||
|
nop
|
||||||
|
stmfd sp!, {r1-r12,lr}
|
||||||
|
nop
|
||||||
|
mrs r12, cpsr
|
||||||
|
stmfd sp!, {r12}
|
||||||
|
nop
|
||||||
|
|
||||||
|
ldr r12,=swi_intr_addr
|
||||||
|
str lr, [r12]
|
||||||
|
nop
|
||||||
|
|
||||||
|
bl _swi_handler_
|
||||||
|
|
||||||
|
ldmfd sp!, {r12}
|
||||||
|
nop
|
||||||
|
msr cpsr_c, r12
|
||||||
|
ldmfd sp!, {r1-r12,lr}
|
||||||
|
nop
|
||||||
|
|
||||||
|
movs pc, lr
|
||||||
|
|
||||||
|
_swi_handler_:
|
||||||
|
ldr r12, =swi_handler
|
||||||
|
bx r12
|
||||||
|
|
||||||
|
|
||||||
|
.thumb_func
|
||||||
|
.align
|
||||||
|
.pool
|
||||||
|
|
||||||
|
.pool
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* IOS mem_exe for load modules (512KB)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.section ".mem_exe" ,"aw",%progbits
|
||||||
|
.global mem_exe
|
||||||
|
mem_exe:
|
||||||
|
.space 0x80000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* IOS data section
|
||||||
|
*
|
||||||
|
* Basically, this is required for the program header not to be messed up
|
||||||
|
* The program header will only be generated correctly if there is "something"
|
||||||
|
* in the ram segment, this makes sure of that by placing a silly string there.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
.section ".ios_data" ,"aw",%progbits
|
||||||
|
.ascii "IOS module"
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* IOS bss section
|
||||||
|
*
|
||||||
|
* This contains the module's thread stack
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
.section ".ios_bss", "a", %nobits
|
||||||
|
.global ios_thread_stack_start /* stack address decrease.. */
|
||||||
|
ios_thread_stack_start:
|
||||||
|
.space ios_thread_stacksize
|
||||||
|
.global ios_thread_stack /* stack address decrease.. */
|
||||||
|
ios_thread_stack:
|
||||||
|
.space 0x900
|
||||||
|
swi_stack:
|
||||||
|
|
||||||
|
.section ".ios_info_table","ax",%progbits
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* IOS info table section
|
||||||
|
*
|
||||||
|
* This contains the module's loader information
|
||||||
|
* The stripios tool will find this, and package it nicely for the IOS system
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
.global ios_info_table
|
||||||
|
ios_info_table:
|
||||||
|
|
||||||
|
.long 0x0
|
||||||
|
.long 0x28 @ numentries * 0x28
|
||||||
|
.long 0x6
|
||||||
|
.long 0xB
|
||||||
|
.long ios_thread_arg @ passed to thread entry func, maybe module id
|
||||||
|
.long 0x9
|
||||||
|
.long _start
|
||||||
|
.long 0x7D
|
||||||
|
.long ios_thread_priority
|
||||||
|
.long 0x7E
|
||||||
|
.long ios_thread_stacksize
|
||||||
|
.long 0x7F
|
||||||
|
.long ios_thread_stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.end
|
964
mload/source/main.c
Normal file
964
mload/source/main.c
Normal file
@ -0,0 +1,964 @@
|
|||||||
|
/*
|
||||||
|
dev/mload: Custom IOS module for Wii, to load ios elfs, initialize USB 2.0 and others uses
|
||||||
|
This module is derived from haxx.elf
|
||||||
|
Copyright (C) 2009-2010 Hermes.
|
||||||
|
Copyright (C) 2008 neimod.
|
||||||
|
|
||||||
|
|
||||||
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* main.c - IOS module main code
|
||||||
|
*
|
||||||
|
*******************************************************************************
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* v1.0 - 26 July 2008 - initial release by neimod
|
||||||
|
* v1.1 - 5 September 2008 - prepared for public release
|
||||||
|
* v1.2 - march 2008 - added some IOTCL, put it into its own module, by kwiirk
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "syscalls.h"
|
||||||
|
#include "swi_mload.h"
|
||||||
|
|
||||||
|
#define MLOAD_VER 5
|
||||||
|
#define MLOAD_SUBVER 2
|
||||||
|
#define STR_VERSION "dev/mload v5.2 (c) 2009-2010, Hermes\n"
|
||||||
|
|
||||||
|
#define IOS_OPEN 0x01
|
||||||
|
#define IOS_CLOSE 0x02
|
||||||
|
#define IOS_READ 0x03
|
||||||
|
#define IOS_WRITE 0x04
|
||||||
|
#define IOS_SEEK 0x05
|
||||||
|
#define IOS_IOCTL 0x06
|
||||||
|
#define IOS_IOCTLV 0x07
|
||||||
|
|
||||||
|
#define MLOAD_MLOAD_THREAD_ID 0x4D4C4400
|
||||||
|
#define MLOAD_GET_IOS_BASE 0x4D4C4401
|
||||||
|
#define MLOAD_GET_MLOAD_VERSION 0x4D4C4402
|
||||||
|
|
||||||
|
#define MLOAD_LOAD_MODULE 0x4D4C4480
|
||||||
|
#define MLOAD_RUN_MODULE 0x4D4C4481
|
||||||
|
#define MLOAD_RUN_THREAD 0x4D4C4482
|
||||||
|
|
||||||
|
#define MLOAD_STOP_THREAD 0x4D4C4484
|
||||||
|
#define MLOAD_CONTINUE_THREAD 0x4D4C4485
|
||||||
|
|
||||||
|
#define MLOAD_GET_LOAD_BASE 0x4D4C4490
|
||||||
|
#define MLOAD_MEMSET 0x4D4C4491
|
||||||
|
|
||||||
|
#define MLOAD_GET_EHCI_DATA 0x4D4C44A0
|
||||||
|
#define MLOAD_GET_LOG 0x4D4C44A1
|
||||||
|
|
||||||
|
#define MLOAD_SET_ES_IOCTLV 0x4D4C44B0
|
||||||
|
#define MLOAD_SET_SYSTEM_FUNC 0x4D4C44B1
|
||||||
|
|
||||||
|
#define MLOAD_GETW 0x4D4C44C0
|
||||||
|
#define MLOAD_GETH 0x4D4C44C1
|
||||||
|
#define MLOAD_GETB 0x4D4C44C2
|
||||||
|
#define MLOAD_SETW 0x4D4C44C3
|
||||||
|
#define MLOAD_SETH 0x4D4C44C4
|
||||||
|
#define MLOAD_SETB 0x4D4C44C5
|
||||||
|
|
||||||
|
#define DEVICE "/dev/mload"
|
||||||
|
|
||||||
|
|
||||||
|
u32 IOS_BASE=0;
|
||||||
|
u8 ES_patch_ioctvl[8] = {
|
||||||
|
0x49, 0x00, 0x47, 0x08, /* addr in mload.elf */ 0x13, 0x8c, 0x00, 0x4+1 // (Thumb)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern void direct_syscall(void);
|
||||||
|
u32 syscall_base=0;
|
||||||
|
|
||||||
|
extern int ES_ioctlv_ret(void *);
|
||||||
|
|
||||||
|
unsigned ES_ioctlv_vect=((unsigned) ES_ioctlv_ret);
|
||||||
|
|
||||||
|
int (*system_mode_func)(void)=0;
|
||||||
|
|
||||||
|
unsigned int heapspace[0x100/4] __attribute__ ((aligned (32)));
|
||||||
|
|
||||||
|
// from IOS ELF stripper of neimod
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 ident0;
|
||||||
|
u32 ident1;
|
||||||
|
u32 ident2;
|
||||||
|
u32 ident3;
|
||||||
|
u32 machinetype;
|
||||||
|
u32 version;
|
||||||
|
u32 entry;
|
||||||
|
u32 phoff;
|
||||||
|
u32 shoff;
|
||||||
|
u32 flags;
|
||||||
|
u16 ehsize;
|
||||||
|
u16 phentsize;
|
||||||
|
u16 phnum;
|
||||||
|
u16 shentsize;
|
||||||
|
u16 shnum;
|
||||||
|
u16 shtrndx;
|
||||||
|
} elfheader;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 type;
|
||||||
|
u32 offset;
|
||||||
|
u32 vaddr;
|
||||||
|
u32 paddr;
|
||||||
|
u32 filesz;
|
||||||
|
u32 memsz;
|
||||||
|
u32 flags;
|
||||||
|
u32 align;
|
||||||
|
} elfphentry;
|
||||||
|
|
||||||
|
#define ioctlv_u8(a) (*((u8*)(a).data))
|
||||||
|
#define ioctlv_u16(a) (*((u16*)(a).data))
|
||||||
|
#define ioctlv_u32(a) (*((u32*)(a).data))
|
||||||
|
#define ioctlv_voidp(a) (a).data
|
||||||
|
|
||||||
|
extern u8 *mem_exe; // size 0x80000 (see crt0.s)
|
||||||
|
|
||||||
|
|
||||||
|
struct _data_elf
|
||||||
|
{
|
||||||
|
void *start;
|
||||||
|
int prio;
|
||||||
|
void *stack;
|
||||||
|
int size_stack;
|
||||||
|
}
|
||||||
|
data_elf;
|
||||||
|
|
||||||
|
#define getbe32(x) ((adr[x]<<24) | (adr[x+1]<<16) | (adr[x+2]<<8) | (adr[x+3]))
|
||||||
|
|
||||||
|
int load_elf(u32 elf);
|
||||||
|
|
||||||
|
u8 *text_log;
|
||||||
|
int text_pos=0;
|
||||||
|
int text_limit=4096;
|
||||||
|
|
||||||
|
extern void *ehci;
|
||||||
|
int tiny_ehci_init(void);
|
||||||
|
|
||||||
|
|
||||||
|
extern void swi_vector(void);
|
||||||
|
extern void load_swi_stack(void);
|
||||||
|
|
||||||
|
|
||||||
|
void direct_os_sync_before_read(void* ptr, int size);
|
||||||
|
void direct_os_sync_after_write(void* ptr, int size);
|
||||||
|
void ic_invalidate(void);
|
||||||
|
|
||||||
|
u32 read_access_perm(void);
|
||||||
|
void write_access_perm(u32 flags);
|
||||||
|
|
||||||
|
void find_and_patch_es(void)
|
||||||
|
{
|
||||||
|
u16 *addr=(u16 *) 0x13A74F00;
|
||||||
|
|
||||||
|
while(((u32) addr)<0x13A76F00)
|
||||||
|
{
|
||||||
|
if(addr[0]==0x2007)
|
||||||
|
{
|
||||||
|
if(addr[1]==0x23A2 || addr[1]==0x4B0B) {addr[0]=0x2000;direct_os_sync_after_write((void *) addr, 2);break;}
|
||||||
|
|
||||||
|
}
|
||||||
|
addr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// call IRQ_software(9) syscall to go here
|
||||||
|
|
||||||
|
int call_system(void)
|
||||||
|
{
|
||||||
|
static int one=1;
|
||||||
|
|
||||||
|
|
||||||
|
if(system_mode_func) return system_mode_func();
|
||||||
|
|
||||||
|
// hack to add SWI vector
|
||||||
|
if(one)
|
||||||
|
{
|
||||||
|
u32 temp;
|
||||||
|
one=0;
|
||||||
|
|
||||||
|
IOS_BASE=0;
|
||||||
|
|
||||||
|
temp=*((volatile u32 *) 0xFFFF0028);
|
||||||
|
|
||||||
|
if(temp==0xFFFF1C70) {IOS_BASE=36;syscall_base= 0xFFFF8980;}
|
||||||
|
else if(temp==0xFFFF1D60) {IOS_BASE=37;syscall_base= 0xFFFF91B0;}
|
||||||
|
else if(temp==0xFFFF1CA0) {IOS_BASE=38;syscall_base= 0xFFFF8AA0;}
|
||||||
|
else if(temp==0xFFFF1F20)
|
||||||
|
{
|
||||||
|
temp=*((volatile u32 *) 0xFFFF00FC);
|
||||||
|
if(temp==0xFFFFD004)
|
||||||
|
{IOS_BASE=57;syscall_base= 0xFFFF9390;}
|
||||||
|
else
|
||||||
|
if(temp==0xFFFFCE24)
|
||||||
|
{IOS_BASE=60;syscall_base= 0xFFFF9390;}
|
||||||
|
}
|
||||||
|
|
||||||
|
ic_invalidate();
|
||||||
|
|
||||||
|
temp=read_access_perm();
|
||||||
|
write_access_perm(0xffffffff);
|
||||||
|
|
||||||
|
direct_os_sync_after_write((void *) &syscall_base, 4);
|
||||||
|
|
||||||
|
// SWI patch
|
||||||
|
|
||||||
|
*((volatile u32 *) 0xFFFF0028)=((u32) swi_vector);
|
||||||
|
|
||||||
|
direct_os_sync_after_write((void *) 0xFFFF0028, 4);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
find_and_patch_es();
|
||||||
|
|
||||||
|
|
||||||
|
// ES PATCH
|
||||||
|
switch(IOS_BASE)
|
||||||
|
{
|
||||||
|
case 36:
|
||||||
|
|
||||||
|
// patch 1
|
||||||
|
|
||||||
|
*((u16 *) 0x13A75026)= 0xE000;
|
||||||
|
direct_os_sync_after_write((void *) 0x13A75026, 2);
|
||||||
|
|
||||||
|
|
||||||
|
// patch 2
|
||||||
|
*((u16 *) 0x20102710)=0xe001;
|
||||||
|
direct_os_sync_after_write((void *) 0x20102710, 2);
|
||||||
|
|
||||||
|
// patch 3
|
||||||
|
*((u16 *) 0x20104F5E)=0x46c0;
|
||||||
|
direct_os_sync_after_write((void *) 0x20104F5E, 2);
|
||||||
|
|
||||||
|
// patch 4
|
||||||
|
*((u16 *) 0x201075EE)=0xe000;
|
||||||
|
direct_os_sync_after_write((void *) 0x201075EE, 2);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 37:
|
||||||
|
/*
|
||||||
|
// patch 1
|
||||||
|
*((u16 *) 0x20100D4A)= 0x2803;
|
||||||
|
direct_os_sync_after_write((void *) 0x20100D4A, 2);
|
||||||
|
*((u16 *) 0x20100DC2)= 0x2803;
|
||||||
|
direct_os_sync_after_write((void *) 0x20100DC2, 2);
|
||||||
|
|
||||||
|
|
||||||
|
// patch 2
|
||||||
|
*((u16 *) 0x201027A8)=0xd201;
|
||||||
|
direct_os_sync_after_write((void *) 0x201027A8, 2);
|
||||||
|
|
||||||
|
// patch 3
|
||||||
|
*((u16 *) 0x201051A6)=0x46c0;
|
||||||
|
direct_os_sync_after_write((void *) 0x201051A6, 2);
|
||||||
|
|
||||||
|
// patch 4
|
||||||
|
*((u16 *) 0x20107A9E)=0xe000;
|
||||||
|
direct_os_sync_after_write((void *) 0x20107A9E, 2);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// patch 1
|
||||||
|
*((u16 *) 0x20100D4A)= 0x2803;
|
||||||
|
direct_os_sync_after_write((void *) 0x20100D4A, 2);
|
||||||
|
*((u16 *) 0x20100DC2)= 0x2803;
|
||||||
|
direct_os_sync_after_write((void *) 0x20100DC2, 2);
|
||||||
|
|
||||||
|
//*((u16 *) 0x20100D64)= 0x429A;
|
||||||
|
//direct_os_sync_after_write((void *) 0x20100D64, 2);
|
||||||
|
|
||||||
|
// FFS access
|
||||||
|
*((u16 *) 0x200012F2)= 0xE001;
|
||||||
|
direct_os_sync_after_write((void *) 0x200012F2, 2);
|
||||||
|
|
||||||
|
|
||||||
|
// patch 2
|
||||||
|
*((u16 *) 0x201027AC)=0xd201;
|
||||||
|
direct_os_sync_after_write((void *) 0x201027AC, 2);
|
||||||
|
|
||||||
|
// patch 3
|
||||||
|
*((u16 *) 0x2010522A)=0x46c0;
|
||||||
|
direct_os_sync_after_write((void *) 0x2010522A, 2);
|
||||||
|
|
||||||
|
// patch 4
|
||||||
|
*((u16 *) 0x20107B22)=0xe000;
|
||||||
|
direct_os_sync_after_write((void *) 0x20107B22, 2);
|
||||||
|
|
||||||
|
// patch 5
|
||||||
|
*((u16 *) 0x20105FC0)=0xe000;
|
||||||
|
direct_os_sync_after_write((void *) 0x20105FC0, 2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 38:
|
||||||
|
|
||||||
|
// patch 1
|
||||||
|
*((u16 *) 0x20100CC8)= 0x2803;
|
||||||
|
direct_os_sync_after_write((void *) 0x20100CC8, 2);
|
||||||
|
|
||||||
|
*((u16 *) 0x20100D40)= 0x2803;
|
||||||
|
direct_os_sync_after_write((void *) 0x20100D40, 2);
|
||||||
|
|
||||||
|
// patch 2
|
||||||
|
*((u16 *) 0x20102724)=0xd201; // 0x20102720
|
||||||
|
direct_os_sync_after_write((void *) 0x20102724, 2);
|
||||||
|
|
||||||
|
// patch 3
|
||||||
|
*((u16 *) 0x20104FF2)=0x46c0; //0x20104F6E
|
||||||
|
direct_os_sync_after_write((void *) 0x20104FF2, 2);
|
||||||
|
|
||||||
|
// patch 4
|
||||||
|
*((u16 *) 0x20107682)=0xe000; //0x201075FE
|
||||||
|
direct_os_sync_after_write((void *) 0x20107682, 2);
|
||||||
|
|
||||||
|
// FFS access
|
||||||
|
*((u16 *) 0x2000347E)= 0xE001;
|
||||||
|
direct_os_sync_after_write((void *) 0x2000347E, 2);
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 57:
|
||||||
|
|
||||||
|
/*// patch 1
|
||||||
|
*((u16 *) 0x20100DA4)= 0x2803;
|
||||||
|
direct_os_sync_after_write((void *) 0x20100DA4, 2);
|
||||||
|
*((u16 *) 0x20100E1C)= 0x2803;
|
||||||
|
direct_os_sync_after_write((void *) 0x20100E1C, 2);
|
||||||
|
|
||||||
|
// patch 2
|
||||||
|
*((u16 *) 0x20102800)=0xd201;
|
||||||
|
direct_os_sync_after_write((void *) 0x20102800, 2);
|
||||||
|
|
||||||
|
// patch 3
|
||||||
|
*((u16 *) 0x2010523A)=0x46c0;
|
||||||
|
direct_os_sync_after_write((void *) 0x2010523A, 2);
|
||||||
|
|
||||||
|
// patch 4
|
||||||
|
*((u16 *) 0x20107B32)=0xe000;
|
||||||
|
direct_os_sync_after_write((void *) 0x20107B32, 2);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// patch 1
|
||||||
|
*((u16 *) 0x20100E74)= 0x2803;
|
||||||
|
direct_os_sync_after_write((void *) 0x20100E74, 2);
|
||||||
|
*((u16 *) 0x20100EEC)= 0x2803;
|
||||||
|
direct_os_sync_after_write((void *) 0x20100EEC, 2);
|
||||||
|
|
||||||
|
// patch 2
|
||||||
|
*((u16 *) 0x20102C74)=0xd201;
|
||||||
|
direct_os_sync_after_write((void *) 0x20102C74, 2);
|
||||||
|
|
||||||
|
// patch 3
|
||||||
|
*((u16 *) 0x2010576A)=0x46c0;
|
||||||
|
direct_os_sync_after_write((void *) 0x2010523A, 2);
|
||||||
|
|
||||||
|
// patch 4
|
||||||
|
*((u16 *) 0x2010849A)=0xe000;
|
||||||
|
direct_os_sync_after_write((void *) 0x2010849A, 2);
|
||||||
|
|
||||||
|
// patch 5
|
||||||
|
*((u16 *) 0x2010650C)=0xe000;
|
||||||
|
direct_os_sync_after_write((void *) 0x2010650C, 2); // ES_DECRYPT pass
|
||||||
|
|
||||||
|
// FFS access
|
||||||
|
*((u16 *) 0x20001306)= 0xE001;
|
||||||
|
direct_os_sync_after_write((void *) 0x20001306, 2);
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 60:
|
||||||
|
|
||||||
|
// patch 1
|
||||||
|
*((u16 *) 0x20100DA4)= 0x2803;
|
||||||
|
direct_os_sync_after_write((void *) 0x20100DA4, 2);
|
||||||
|
*((u16 *) 0x20100E1C)= 0x2803;
|
||||||
|
direct_os_sync_after_write((void *) 0x20100E1C, 2);
|
||||||
|
|
||||||
|
// patch 2
|
||||||
|
*((u16 *) 0x20102800)=0xd201;
|
||||||
|
direct_os_sync_after_write((void *) 0x20102800, 2);
|
||||||
|
|
||||||
|
// patch 3
|
||||||
|
*((u16 *) 0x2010523A)=0x46c0;
|
||||||
|
direct_os_sync_after_write((void *) 0x2010523A, 2);
|
||||||
|
|
||||||
|
// patch 4
|
||||||
|
*((u16 *) 0x20107B32)=0xe000;
|
||||||
|
direct_os_sync_after_write((void *) 0x20107B32, 2);
|
||||||
|
|
||||||
|
// patch 5
|
||||||
|
*((u16 *) 0x20105FD0)=0xe000;
|
||||||
|
direct_os_sync_after_write((void *) 0x20105FD0, 2); // ES_DECRYPT pass
|
||||||
|
|
||||||
|
// FFS access
|
||||||
|
*((u16 *) 0x20001306)= 0xE001;
|
||||||
|
direct_os_sync_after_write((void *) 0x20001306, 2);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ES ioctlv patch
|
||||||
|
direct_os_sync_after_write((void *) ES_ioctlv_vect,4);
|
||||||
|
|
||||||
|
memcpy((void *) 0x201000CC, (void *) ES_patch_ioctvl, 8);
|
||||||
|
|
||||||
|
direct_os_sync_after_write((void *) 0x201000CC, 8);
|
||||||
|
|
||||||
|
write_access_perm(temp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0x555;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// SWI handler
|
||||||
|
|
||||||
|
u8 * swi_intr_addr;
|
||||||
|
|
||||||
|
int (*swi_table[256]) (u32 arg0, u32 arg1,u32 arg2, u32 arg3);
|
||||||
|
|
||||||
|
int (* swi_func)(void * in, void * out);
|
||||||
|
|
||||||
|
int swi_handler(u32 arg0, u32 arg1,u32 arg2, u32 arg3)
|
||||||
|
{
|
||||||
|
|
||||||
|
// detect SWI instruction
|
||||||
|
|
||||||
|
// 32 bits aligned
|
||||||
|
if(swi_intr_addr[-4]==0xdf) swi_intr_addr-=3; // 16 bits function
|
||||||
|
else swi_intr_addr--; // 32 bits function
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(*(swi_intr_addr)==0xcc)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch(arg0)
|
||||||
|
{
|
||||||
|
// add SWI handler
|
||||||
|
case 0:
|
||||||
|
swi_table[arg1]= (void *) arg2;
|
||||||
|
break;
|
||||||
|
// get EHCI DATA
|
||||||
|
case 1:
|
||||||
|
return (int) ehci;
|
||||||
|
// memcpy ( RAM cached to cached)
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
u32 temp;
|
||||||
|
temp=read_access_perm();
|
||||||
|
write_access_perm(0xffffffff);
|
||||||
|
memcpy((void *) arg1, (void *) arg2, arg3);
|
||||||
|
direct_os_sync_after_write((void *) arg1, arg3);
|
||||||
|
write_access_perm(temp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// get register
|
||||||
|
case 3:
|
||||||
|
return *((volatile u32 *) arg1);
|
||||||
|
// put register
|
||||||
|
case 4:
|
||||||
|
*((volatile u32 *) arg1)=arg2;
|
||||||
|
break;
|
||||||
|
// set register
|
||||||
|
case 5:
|
||||||
|
*((volatile u32 *) arg1)|=arg2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// clr register
|
||||||
|
case 6:
|
||||||
|
*((volatile u32 *) arg1)&=~arg2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// function to call in os_software_IRQ(9)
|
||||||
|
case 7:
|
||||||
|
system_mode_func=(void *) arg1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// log buffer function
|
||||||
|
case 8:
|
||||||
|
switch(arg1)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
memset( (void *) text_log, 0, text_limit);
|
||||||
|
text_pos=0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
text_pos= 0;
|
||||||
|
text_log= (void *) arg2;
|
||||||
|
text_limit= (int) arg3;
|
||||||
|
memset( (void *) text_log, 0, text_limit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (int) text_log;
|
||||||
|
case 9:
|
||||||
|
// memcpy ( RAM uncached to cached)
|
||||||
|
{
|
||||||
|
u32 temp;
|
||||||
|
temp=read_access_perm();
|
||||||
|
write_access_perm(0xffffffff);
|
||||||
|
direct_os_sync_before_read((void *) arg2, arg3);
|
||||||
|
memcpy((void *) arg1, (void *) arg2, arg3);
|
||||||
|
direct_os_sync_after_write((void *) arg1, arg3);
|
||||||
|
write_access_perm(temp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// call func
|
||||||
|
case 16:
|
||||||
|
swi_func= (void *) arg1;
|
||||||
|
return swi_func((void *) arg2, (void *) arg3);
|
||||||
|
|
||||||
|
// get syscalls base
|
||||||
|
case 17:
|
||||||
|
return ((int) syscall_base);
|
||||||
|
|
||||||
|
// get IOS base
|
||||||
|
case 18:
|
||||||
|
return ((int) IOS_BASE);
|
||||||
|
|
||||||
|
// get mload version
|
||||||
|
case 19:
|
||||||
|
return ((MLOAD_VER<<4)+MLOAD_SUBVER);
|
||||||
|
|
||||||
|
// led on
|
||||||
|
case 128:
|
||||||
|
*((volatile u32 *)0x0d8000c0) |=0x20;
|
||||||
|
break;
|
||||||
|
// led off
|
||||||
|
case 129:
|
||||||
|
*((volatile u32 *)0x0d8000c0) &=~0x20;
|
||||||
|
break;
|
||||||
|
// led blink
|
||||||
|
case 130:
|
||||||
|
*((volatile u32 *)0x0d8000c0) ^=0x20;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
// test
|
||||||
|
case 200:
|
||||||
|
if(arg3==0x666)
|
||||||
|
*((volatile u32 *)0x0d8000c0) |=0x20;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(swi_table[*(swi_intr_addr)]) return swi_table[*(swi_intr_addr)](arg0, arg1, arg2, arg3);
|
||||||
|
else return arg0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int swi_handler_text(u32 arg0, u32 arg1,u32 arg2, u32 arg3)
|
||||||
|
{
|
||||||
|
int n,max;
|
||||||
|
u8 *p;
|
||||||
|
|
||||||
|
if(arg0!=4) return (int) arg0;
|
||||||
|
|
||||||
|
p=(u8 *) arg1;
|
||||||
|
|
||||||
|
for(n=0;n<40*3;n++) if(p[n]==0) break;
|
||||||
|
|
||||||
|
max=(text_limit/40)*40;
|
||||||
|
|
||||||
|
if((text_pos+n)>(max))
|
||||||
|
{
|
||||||
|
text_pos=max-n;
|
||||||
|
memcpy((void *) &text_log[0],(void *) &text_log[n], max-n);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy((void *) &text_log[text_pos], (void *) p, n);
|
||||||
|
text_pos+=n;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int shadow_mload=0;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
ipcmessage* message;
|
||||||
|
unsigned int offset = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
mem_exe[0]=0; // don't remove this !!!!!
|
||||||
|
|
||||||
|
|
||||||
|
tiny_ehci_init();
|
||||||
|
|
||||||
|
unsigned int heaphandle = os_heap_create(heapspace, sizeof(heapspace));
|
||||||
|
void* queuespace = os_heap_alloc(heaphandle, 0x20);
|
||||||
|
|
||||||
|
unsigned int queuehandle = os_message_queue_create(queuespace, 8);
|
||||||
|
|
||||||
|
memset( (void *) swi_table,0, 256);
|
||||||
|
swi_table[0xab]= swi_handler_text;
|
||||||
|
memset( (void *) text_log, 0, text_limit);
|
||||||
|
|
||||||
|
|
||||||
|
os_software_IRQ(9); // patch the SWI vector (see call_system())
|
||||||
|
|
||||||
|
os_device_register(DEVICE, queuehandle);
|
||||||
|
|
||||||
|
os_puts(STR_VERSION);
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
int result = 1;
|
||||||
|
int ack = 1;
|
||||||
|
|
||||||
|
// Wait for message to arrive
|
||||||
|
os_message_queue_receive(queuehandle, (void*)&message, 0);
|
||||||
|
|
||||||
|
switch( message->command )
|
||||||
|
{
|
||||||
|
case IOS_OPEN:
|
||||||
|
{
|
||||||
|
//debug_printf("%s try open %sfor fd %d\n",DEVICE,message->open.device,message->open.resultfd);
|
||||||
|
// Checking device name
|
||||||
|
if (0 == strcmp(message->open.device, DEVICE))
|
||||||
|
{
|
||||||
|
if(shadow_mload) result=-6;
|
||||||
|
else result = message->open.resultfd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == strcmp(message->open.device, DEVICE"/OFF"))
|
||||||
|
{
|
||||||
|
shadow_mload=1;
|
||||||
|
result=-6;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
result = -6;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOS_CLOSE:
|
||||||
|
{
|
||||||
|
|
||||||
|
// do nothing
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOS_READ:
|
||||||
|
{
|
||||||
|
// Read from Starlet memory
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// NOTE: no aligned is better
|
||||||
|
memcpy(message->read.data, (void*)offset, message->read.length);
|
||||||
|
// Clean cache
|
||||||
|
os_sync_after_write( message->read.data, message->read.length );
|
||||||
|
#else
|
||||||
|
swi_mload_memcpy_from_uncached((void *) message->read.data, (void*)offset, message->read.length);
|
||||||
|
offset += message->read.length;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOS_WRITE:
|
||||||
|
{
|
||||||
|
// Write to Starlet memory
|
||||||
|
// Invalidate cache
|
||||||
|
#if 0
|
||||||
|
os_sync_before_read( message->write.data, message->write.length );
|
||||||
|
memcpy((void*)offset, message->write.data, message->write.length);
|
||||||
|
#else
|
||||||
|
swi_mload_memcpy((void*)offset, message->write.data, message->write.length);
|
||||||
|
offset += message->write.length;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOS_SEEK:
|
||||||
|
{
|
||||||
|
// Change current offset
|
||||||
|
switch(message->seek.origin)
|
||||||
|
{
|
||||||
|
case SEEK_SET:
|
||||||
|
{
|
||||||
|
offset = message->seek.offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SEEK_CUR:
|
||||||
|
{
|
||||||
|
offset += message->seek.offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SEEK_END:
|
||||||
|
{
|
||||||
|
offset = - message->seek.offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result=offset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case IOS_IOCTL:
|
||||||
|
{
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IOS_IOCTLV:
|
||||||
|
{
|
||||||
|
ioctlv *vec = message->ioctlv.vector;
|
||||||
|
|
||||||
|
int i,in = message->ioctlv.num_in,io= message->ioctlv.num_io;
|
||||||
|
|
||||||
|
os_sync_before_read( vec, (in+io)*sizeof(ioctlv));
|
||||||
|
|
||||||
|
for(i=0;i<in+io;i++){
|
||||||
|
os_sync_before_read( vec[i].data, vec[i].len);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( message->ioctl.command )
|
||||||
|
{
|
||||||
|
|
||||||
|
case MLOAD_MLOAD_THREAD_ID:
|
||||||
|
|
||||||
|
result=os_get_thread_id();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MLOAD_GET_IOS_BASE:
|
||||||
|
result= (u32) IOS_BASE;
|
||||||
|
break;
|
||||||
|
case MLOAD_GET_MLOAD_VERSION:
|
||||||
|
result= (u32) ((MLOAD_VER<<4)+MLOAD_SUBVER);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MLOAD_GET_EHCI_DATA:
|
||||||
|
|
||||||
|
result= (u32) ehci;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MLOAD_GET_LOAD_BASE:
|
||||||
|
|
||||||
|
result=0;
|
||||||
|
ioctlv_u32(vec[0])= 0x13700000;
|
||||||
|
ioctlv_u32(vec[1])= 0x80000;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MLOAD_LOAD_MODULE:
|
||||||
|
|
||||||
|
result = load_elf((u32) ioctlv_voidp(vec[0]));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MLOAD_RUN_MODULE:
|
||||||
|
|
||||||
|
result=os_thread_create( data_elf.start, NULL, data_elf.stack, data_elf.size_stack, data_elf.prio, 0);
|
||||||
|
if(result>=0) os_thread_continue(result);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MLOAD_RUN_THREAD:
|
||||||
|
|
||||||
|
result=os_thread_create((void *) ioctlv_u32(vec[0]), NULL, (void *) ioctlv_u32(vec[1]), ioctlv_u32(vec[2]), ioctlv_u32(vec[3]), 0);
|
||||||
|
if(result>=0) os_thread_continue(result);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MLOAD_STOP_THREAD:
|
||||||
|
|
||||||
|
result=os_thread_stop(ioctlv_u32(vec[0]));
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MLOAD_CONTINUE_THREAD:
|
||||||
|
|
||||||
|
result=os_thread_continue(ioctlv_u32(vec[0]));
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case MLOAD_MEMSET:
|
||||||
|
result=0;
|
||||||
|
os_sync_before_read((void *) ioctlv_u32(vec[0]), ioctlv_u32(vec[2]));
|
||||||
|
memset((void *) ioctlv_u32(vec[0]), ioctlv_u32(vec[1]), ioctlv_u32(vec[2]));
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MLOAD_SET_ES_IOCTLV: // changes the current vector for dev/es ioctl (put 0 to disable it)
|
||||||
|
result=0;
|
||||||
|
|
||||||
|
ES_ioctlv_vect=ioctlv_u32(vec[0]);
|
||||||
|
os_sync_after_write( &ES_ioctlv_vect, 4);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MLOAD_SET_SYSTEM_FUNC:
|
||||||
|
result=0;
|
||||||
|
|
||||||
|
system_mode_func=(void *) ioctlv_u32(vec[0]);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MLOAD_GET_LOG:
|
||||||
|
result=text_limit;
|
||||||
|
offset =(unsigned int) text_log;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case MLOAD_GETW:
|
||||||
|
result=0;
|
||||||
|
ioctlv_u32(vec[1])=*((volatile u32*) ioctlv_u32(vec[0]));
|
||||||
|
break;
|
||||||
|
case MLOAD_GETH:
|
||||||
|
result=0;
|
||||||
|
ioctlv_u16(vec[1])=*((volatile u16*) ioctlv_u32(vec[0]));
|
||||||
|
break;
|
||||||
|
case MLOAD_GETB:
|
||||||
|
result=0;
|
||||||
|
ioctlv_u8(vec[1])=*((volatile u8*) ioctlv_u32(vec[0]));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MLOAD_SETW:
|
||||||
|
result=0;
|
||||||
|
*((volatile u32*) ioctlv_u32(vec[0]))=ioctlv_u32(vec[1]);
|
||||||
|
break;
|
||||||
|
case MLOAD_SETH:
|
||||||
|
result=0;
|
||||||
|
*((volatile u16*) ioctlv_u32(vec[0]))=ioctlv_u16(vec[1]);
|
||||||
|
break;
|
||||||
|
case MLOAD_SETB:
|
||||||
|
result=0;
|
||||||
|
*((volatile u8*) ioctlv_u32(vec[0]))=ioctlv_u8(vec[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
for(i=in;i<in+io;i++){
|
||||||
|
os_sync_after_write( vec[i].data, vec[i].len);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
result = -1;
|
||||||
|
//ack = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//debug_printf("return %d\n",result);
|
||||||
|
// Acknowledge message
|
||||||
|
if (ack)
|
||||||
|
os_message_queue_ack( (void*)message, result );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int load_elf(u32 elf)
|
||||||
|
{
|
||||||
|
int n,m;
|
||||||
|
int p;
|
||||||
|
u8 *adr;
|
||||||
|
|
||||||
|
elfheader *head=(void *) elf;
|
||||||
|
elfphentry *entries;
|
||||||
|
|
||||||
|
if(head->ident0!=0x7F454C46) return -1;
|
||||||
|
if(head->ident1!=0x01020161) return -1;
|
||||||
|
if(head->ident2!=0x01000000) return -1;
|
||||||
|
|
||||||
|
p=head->phoff;
|
||||||
|
|
||||||
|
data_elf.start=(void *) head->entry;
|
||||||
|
|
||||||
|
for(n=0; n<head->phnum; n++)
|
||||||
|
{
|
||||||
|
entries=(void *) (elf+p);
|
||||||
|
p+=sizeof(elfphentry);
|
||||||
|
|
||||||
|
if(entries->type == 4)
|
||||||
|
{
|
||||||
|
adr=(void *) (elf + entries->offset);
|
||||||
|
|
||||||
|
if(getbe32(0)!=0) return -2; // bad info (sure)
|
||||||
|
|
||||||
|
for(m=4; m < entries->memsz; m+=8)
|
||||||
|
{
|
||||||
|
switch(getbe32(m))
|
||||||
|
{
|
||||||
|
case 0x9:
|
||||||
|
data_elf.start= (void *) getbe32(m+4);
|
||||||
|
break;
|
||||||
|
case 0x7D:
|
||||||
|
data_elf.prio= getbe32(m+4);
|
||||||
|
break;
|
||||||
|
case 0x7E:
|
||||||
|
data_elf.size_stack= getbe32(m+4);
|
||||||
|
break;
|
||||||
|
case 0x7F:
|
||||||
|
data_elf.stack= (void *) (getbe32(m+4));
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(entries->type == 1 && entries->memsz != 0 && entries->vaddr!=0)
|
||||||
|
{
|
||||||
|
|
||||||
|
os_sync_before_read((void *) entries->vaddr, entries->memsz );
|
||||||
|
|
||||||
|
memset((void *) entries->vaddr, 0, entries->memsz);
|
||||||
|
memcpy((void *) entries->vaddr, (void *) (elf + entries->offset), entries->filesz);
|
||||||
|
|
||||||
|
os_sync_after_write((void *) entries->vaddr, entries->memsz );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
301
mload/source/tiny_ehci_glue.c
Normal file
301
mload/source/tiny_ehci_glue.c
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
/*
|
||||||
|
EHCI glue. A bit hacky for the moment. needs cleaning..
|
||||||
|
|
||||||
|
Copyright (C) 2008 kwiirk.
|
||||||
|
|
||||||
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include "syscalls.h"
|
||||||
|
|
||||||
|
#include "ehci_types.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#define static
|
||||||
|
#define inline extern
|
||||||
|
|
||||||
|
|
||||||
|
#define readl(a) (*((volatile u32*)(a)))
|
||||||
|
#define writel(v,a) do{*((volatile u32*)(a))=(v);}while(0)
|
||||||
|
#define ehci_dbg(a...) debug_printf(a)
|
||||||
|
#define printk(a...) debug_printf(a)
|
||||||
|
#define get_timer() (*(((volatile u32*)0x0D800010)))
|
||||||
|
|
||||||
|
|
||||||
|
void BUG(void)
|
||||||
|
{
|
||||||
|
debug_printf("bug\n");
|
||||||
|
// stack_trace();
|
||||||
|
// while(1);
|
||||||
|
}
|
||||||
|
#define BUG_ON(a) if(a)BUG()
|
||||||
|
|
||||||
|
|
||||||
|
void udelay(int usec)
|
||||||
|
{
|
||||||
|
u32 tmr,temp;
|
||||||
|
u32 time_usec;
|
||||||
|
|
||||||
|
tmr = get_timer();
|
||||||
|
time_usec=2*usec;
|
||||||
|
|
||||||
|
while (1) {temp=get_timer()-tmr;if(temp > time_usec) break;}
|
||||||
|
|
||||||
|
}
|
||||||
|
void msleep(int msec)//@todo not really sleeping..
|
||||||
|
{
|
||||||
|
u32 tmr,temp;
|
||||||
|
u32 time_usec;
|
||||||
|
|
||||||
|
tmr = get_timer();
|
||||||
|
time_usec=2048*msec;
|
||||||
|
|
||||||
|
while (1) {temp=get_timer()-tmr;if(temp > time_usec) break;}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
extern u32 __exe_start_virt__;
|
||||||
|
extern u32 __ram_start_virt__;
|
||||||
|
|
||||||
|
extern u32 ios_thread_stack;
|
||||||
|
|
||||||
|
#define cpu_to_le32(a) swab32(a)
|
||||||
|
#define le32_to_cpu(a) swab32(a)
|
||||||
|
#define cpu_to_le16(a) swab16(a)
|
||||||
|
#define le16_to_cpu(a) swab16(a)
|
||||||
|
#define cpu_to_be32(a) (a)
|
||||||
|
#define be32_to_cpu(a) (a)
|
||||||
|
void print_hex_dump_bytes(char *header,int prefix,u8 *buf,int len)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#define DUMP_PREFIX_OFFSET 1
|
||||||
|
#include "ehci.h"
|
||||||
|
#define ehci_readl(a) ((*((volatile u32*)(a))))
|
||||||
|
//#define ehci_writel(e,v,a) do{msleep(40);debug_printf("writel %08X %08X\n",a,v);*((volatile u32*)(a))=(v);}while(0)
|
||||||
|
#define ehci_writel(v,a) do{*((volatile u32*)(a))=(v);}while(0)
|
||||||
|
|
||||||
|
struct ehci_hcd _ehci;
|
||||||
|
struct ehci_hcd *ehci = &_ehci;
|
||||||
|
|
||||||
|
//#include "ehci.c"
|
||||||
|
|
||||||
|
u8 heap_space2[0x5000] __attribute__ ((aligned (32)));
|
||||||
|
|
||||||
|
#include "ehci-mem.c"
|
||||||
|
|
||||||
|
//static usbctrlrequest mem_usbctrlrequest __attribute__ ((aligned (32)));
|
||||||
|
static u8 mem_usbctrlrequest[sizeof(usbctrlrequest)+32] __attribute__ ((aligned (32)));
|
||||||
|
static int ehci_init(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
if ((retval = ehci_mem_init()) < 0)
|
||||||
|
return retval;
|
||||||
|
/*
|
||||||
|
* dedicate a qh for the async ring head, since we couldn't unlink
|
||||||
|
* a 'real' qh without stopping the async schedule [4.8]. use it
|
||||||
|
* as the 'reclamation list head' too.
|
||||||
|
* its dummy is used in hw_alt_next of many tds, to prevent the qh
|
||||||
|
* from automatically advancing to the next td after short reads.
|
||||||
|
*/
|
||||||
|
ehci->async->hw_next = QH_NEXT( ehci->async->qh_dma);
|
||||||
|
ehci->async->hw_info1 = cpu_to_hc32( QH_HEAD);
|
||||||
|
ehci->async->hw_token = cpu_to_hc32( QTD_STS_HALT);
|
||||||
|
ehci->async->hw_qtd_next = EHCI_LIST_END();
|
||||||
|
ehci->async->hw_alt_next = EHCI_LIST_END();//QTD_NEXT( ehci->async->dummy->qtd_dma);
|
||||||
|
ehci->ctrl_buffer = mem_usbctrlrequest ;//USB_Alloc(sizeof(usbctrlrequest));
|
||||||
|
ehci->command = 0;
|
||||||
|
|
||||||
|
ehci_dma_map_bidir(ehci->async,sizeof(struct ehci_qh));
|
||||||
|
|
||||||
|
ehci_writel( 0x008000002, &ehci->regs->command);
|
||||||
|
msleep(20);
|
||||||
|
ehci_writel( ehci->periodic_dma, &ehci->regs->frame_list);
|
||||||
|
ehci_writel( ehci->async->qh_dma, &ehci->regs->async_next);
|
||||||
|
ehci_writel( 0x00010001, &ehci->regs->command);
|
||||||
|
msleep(20);
|
||||||
|
ehci_writel( 1, &ehci->regs->configured_flag);
|
||||||
|
ehci_writel( 0x00010021, &ehci->regs->command);
|
||||||
|
msleep(20);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
int ehci_adquire_port(int port)
|
||||||
|
{
|
||||||
|
u32 __iomem *status_reg = &ehci->regs->port_status[port];
|
||||||
|
u32 status = ehci_readl(status_reg);
|
||||||
|
|
||||||
|
//change owner, port disabled
|
||||||
|
if(status & PORT_OWNER)
|
||||||
|
{
|
||||||
|
status ^= PORT_OWNER;
|
||||||
|
status &= ~(PORT_PE | PORT_RWC_BITS);
|
||||||
|
ehci_writel(status, status_reg);
|
||||||
|
msleep(5);
|
||||||
|
status = ehci_readl(status_reg);
|
||||||
|
}
|
||||||
|
ehci_writel( 0x1803,status_reg);
|
||||||
|
msleep(100);
|
||||||
|
ehci_writel( 0x1903,status_reg);
|
||||||
|
msleep(100);// wait 100ms for the reset sequence
|
||||||
|
ehci_writel( 0x1801,status_reg);
|
||||||
|
msleep(60);
|
||||||
|
#if 0
|
||||||
|
status &= ~PORT_PE;
|
||||||
|
status |= 0x800 | PORT_RESET | PORT_POWER;
|
||||||
|
ehci_writel( status,status_reg);
|
||||||
|
msleep(60);// wait 60ms for the reset sequence
|
||||||
|
status=ehci_readl(status_reg);
|
||||||
|
status &= ~(PORT_RWC_BITS | PORT_RESET); // force reset to complete
|
||||||
|
ehci_writel( status,status_reg);
|
||||||
|
msleep(60);
|
||||||
|
//enable port
|
||||||
|
#endif
|
||||||
|
|
||||||
|
status = ehci_readl(status_reg);
|
||||||
|
|
||||||
|
if((status & PORT_OWNER) || PORT_USB11(status)) return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
extern u8 *text_log;
|
||||||
|
|
||||||
|
int tiny_ehci_init(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
// int n;
|
||||||
|
ehci = &_ehci;
|
||||||
|
|
||||||
|
|
||||||
|
ehci->caps = (void*)0x0D040000;
|
||||||
|
ehci->regs = (void*)(0x0D040000 +
|
||||||
|
HC_LENGTH(ehci_readl(&ehci->caps->hc_capbase)));
|
||||||
|
ehci->num_port = 4; // aqui numero de puertos usb
|
||||||
|
/* cache this readonly data; minimize chip reads */
|
||||||
|
ehci->hcs_params = ehci_readl(&ehci->caps->hcs_params);
|
||||||
|
|
||||||
|
text_log=ehci_maligned(4096, 4096, 4096);
|
||||||
|
|
||||||
|
/* data structure init */
|
||||||
|
retval = ehci_init();
|
||||||
|
if (retval)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
|
||||||
|
ehci_release_ports(); //quickly release all ports
|
||||||
|
/*
|
||||||
|
#ifdef USE_USB_PORT_1
|
||||||
|
|
||||||
|
ehci_writel( PORT_OWNER, &ehci->regs->port_status[0]); // force port 0 to work as USB 1.1
|
||||||
|
|
||||||
|
for(n=0;n<3;n++)
|
||||||
|
{
|
||||||
|
if(!ehci_adquire_port(1)) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
ehci_writel( PORT_OWNER, &ehci->regs->port_status[1]); // force port 1 to work as USB 1.1
|
||||||
|
|
||||||
|
for(n=0;n<3;n++)
|
||||||
|
{
|
||||||
|
if(!ehci_adquire_port(0)) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ehci_release_ports(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u32 __iomem *status_reg = &ehci->regs->port_status[2];
|
||||||
|
while(ehci_readl(&ehci->regs->port_status[2]) == 0x1000);// wait port 2 to init
|
||||||
|
msleep(1);// wait another msec..
|
||||||
|
for(i = 0;i<ehci->num_port; i++){ //release all ports
|
||||||
|
status_reg = &ehci->regs->port_status[i];
|
||||||
|
//u32 status = ehci_readl(status_reg);
|
||||||
|
//if (i==2 || !(PORT_CONNECT&status) || PORT_USB11(status))
|
||||||
|
ehci_writel( PORT_OWNER,status_reg); // release port.
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8* aligned_mem = 0;
|
||||||
|
static u8* aligned_base = 0;
|
||||||
|
/* @todo hum.. not that nice.. */
|
||||||
|
void*ehci_maligned(int size,int alignement,int crossing)
|
||||||
|
{
|
||||||
|
if (!aligned_mem )
|
||||||
|
{
|
||||||
|
aligned_mem=aligned_base = (u8 *)((((u32) heap_space2+4095) & ~4095));//(void*)0x13890000;
|
||||||
|
}
|
||||||
|
u32 addr=(u32)aligned_mem;
|
||||||
|
alignement--;
|
||||||
|
addr += alignement;
|
||||||
|
addr &= ~alignement;
|
||||||
|
if (((addr +size-1)& ~(crossing-1)) != (addr&~(crossing-1)))
|
||||||
|
addr = (addr +size-1)&~(crossing-1);
|
||||||
|
aligned_mem = (void*)(addr + size);
|
||||||
|
if (aligned_mem>aligned_base + 0x4000)
|
||||||
|
{
|
||||||
|
debug_printf("not enough aligned memory!\n");
|
||||||
|
while(1) msleep(1);
|
||||||
|
}
|
||||||
|
memset((void*)addr,0,size);
|
||||||
|
return (void*)addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_addr_t ehci_virt_to_dma(void *a)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (dma_addr_t)a;
|
||||||
|
}
|
||||||
|
dma_addr_t ehci_dma_map_to(void *buf,size_t len)
|
||||||
|
{
|
||||||
|
os_sync_after_write(buf, len);
|
||||||
|
return (dma_addr_t)buf;
|
||||||
|
|
||||||
|
}
|
||||||
|
dma_addr_t ehci_dma_map_from(void *buf,size_t len)
|
||||||
|
{
|
||||||
|
os_sync_after_write(buf, len);
|
||||||
|
return (dma_addr_t)buf;
|
||||||
|
}
|
||||||
|
dma_addr_t ehci_dma_map_bidir(void *buf,size_t len)
|
||||||
|
{
|
||||||
|
//debug_printf("sync_after_write %p %x\n",buf,len);
|
||||||
|
|
||||||
|
os_sync_after_write(buf, len);
|
||||||
|
return (dma_addr_t)buf;
|
||||||
|
}
|
||||||
|
void ehci_dma_unmap_to(dma_addr_t buf,size_t len)
|
||||||
|
{
|
||||||
|
os_sync_before_read((void*)buf, len);
|
||||||
|
}
|
||||||
|
void ehci_dma_unmap_from(dma_addr_t buf,size_t len)
|
||||||
|
{
|
||||||
|
os_sync_before_read((void*)buf, len);
|
||||||
|
}
|
||||||
|
void ehci_dma_unmap_bidir(dma_addr_t buf,size_t len)
|
||||||
|
{
|
||||||
|
os_sync_before_read((void*)buf, len);
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user