Compare commits

..
Author SHA1 Message Date
CLARATION c98dd080dd Merge branch 'main' into koputer 2026-08-03 09:45:25 -07:00
CLARATION ec64322177 chore: update jbinit 2026-08-03 09:43:56 -07:00
CLARATION 8d2fa31bc9 fix: do proper checks for pongo bin 2026-08-02 20:34:22 -07:00
CLARATION 27eb58e188 fix(build): wtf 2026-08-02 19:26:42 -07:00
CLARATION bba50ee092 refactor(build): move things in their own files 2026-08-02 19:00:28 -07:00
CLARATION 89bcddcb4b fix(tui): settings back button being broken xd 2026-08-01 21:21:22 -07:00
CLARATION 8f517976ba feat(wx/tui): add --force-enable-ssv to options 2026-08-01 21:10:38 -07:00
CLARATION 9c3a591db8 fix(wx): remove disconnects handling during dfu transition
when the text "device has entered dfu" appeared, theres a 3 second window where it waits until it transitions to the exploit screen, and during that moment device disconnect handling was being incorrectly handled when it shouldnt of been
2026-08-01 18:59:47 -07:00
CLARATION 02fe95fbfc fix(tui/wx): remove device check in exploit panel 2026-08-01 18:57:34 -07:00
CLARATION b760cc1d83 chore(ci): update loader 2026-08-01 05:09:13 -07:00
CLARATION a7af7a4041 chore: remove this todo 2026-08-01 04:16:07 -07:00
CLARATION 36dc0137bd fix: check if boot command (forgot) 2026-08-01 04:07:21 -07:00
CLARATION 7fe32b54c9 chore: remove useless checks 2026-08-01 03:47:54 -07:00
CLARATION c70c2506ad feat(docs): add --late-exit 2026-08-01 03:24:28 -07:00
CLARATION 7c6c52904e fix: incorrect handling of flag checks 2026-08-01 03:18:04 -07:00
CLARATION ef88661453 fix: redo issue_pongo_command, add error msg 2026-08-01 02:36:08 -07:00
CLARATION 68358829d6 fix(ci): use proper entitlements for ios 2026-08-01 01:15:52 -07:00
CLARATION 892e17741f fix(ci): ciderrain not ciderra1n 2026-08-01 00:33:26 -07:00
CLARATION 83489e54ea fix(ci): install brew make
fix(ci): use gnumake for pongo
2026-08-01 00:24:27 -07:00
CLARATION da8c45465a chore: minify dfuhelperinfo 2026-07-31 22:06:11 -07:00
CLARATION 3d0e269244 feat: add homepod/t2 devices to dfuhelperinfo 2026-07-31 21:57:13 -07:00
CLARATION b40e137a37 feat(tui/wx): support pongo/dfu modes 2026-07-31 21:38:43 -07:00
CLARATION 7ed291dd46 fix(wx): quick mode not activating dfu sequence 2026-07-31 20:56:58 -07:00
Nick Chan 2d7882051e Makefile and actions fixes
Signed-off-by: Nick Chan <[email protected]>
2026-07-30 21:47:50 +08:00
CLARATION cab5a9f9f8 chore(build): remove cider ios check 2026-07-30 02:53:11 -07:00
Nick Chan 0b2ba0e76e cmake: Fix dependencies deployment target
Signed-off-by: Nick Chan <[email protected]>
2026-07-30 17:10:48 +08:00
CLARATION 795cb3d126 chore(build): dont rebuild idevice each time 2026-07-30 00:50:15 -07:00
CLARATION 0801d52c97 feat(wx): add basic menubar for quit 2026-07-29 23:44:42 -07:00
bradleytechman 1481ecc512 feat(wx): Make the donate button actually do something (#769) 2026-07-27 23:16:19 -07:00
CLARATION 96486d6267 chore(ci): move this down 2026-07-27 16:42:17 -07:00
CLARATION 2720826c22 feat(ci): upload to cdn after release 2026-07-27 16:35:10 -07:00
CLARATION 81b47ab254 fix(wx): add newline for multiple devices 2026-07-27 16:25:24 -07:00
CLARATION 9c65425f7c chore: update credits 2026-07-27 16:16:21 -07:00
Nick Chan e9e44e6cc9 Add Missing Adapter devices
Signed-off-by: Nick Chan <[email protected]>
2026-07-27 18:17:28 +08:00
sealldev 3ba32c40db Fix DFU button guidance for iPod 9,1 (#766) 2026-07-27 16:17:34 +08:00
Nick Chan ad72f91ee8 Update libciderra1n
Signed-off-by: Nick Chan <[email protected]>
2026-07-27 16:05:11 +08:00
CLARATION 97138e24de feat(ci): auto bump palen1x 2026-07-26 19:24:41 -07:00
CLARATION 15d13529a8 fix(ci): checkout repo when downloading releases
also have something for workflow dispatches, so we dont need to upload them manually
2026-07-26 17:48:27 -07:00
CLARATION 337604c25d fix(docs): incorrect placement of a few lines 2026-07-26 17:42:12 -07:00
CLARATION eddcedcca1 feat: install script dmg support, beta & release tag support 2026-07-26 14:29:46 -07:00
38 changed files with 1086 additions and 667 deletions

No files matched your search

+18 -12
View File
@@ -20,7 +20,7 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
ref: a766a91bf4b691317df24d3be41e44e754a3e0d8
ref: 9faf50968854aa47de65231e2985d60f6944d627
repository: palera1n/loader
- name: Install dependencies (brew)
@@ -52,7 +52,7 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
ref: 9cadaa63569ba318677b4ef0869ad984b3663a6c
ref: 7e1f6e122c3a45fc45e939293c7e2eaa1889731f
repository: palera1n/jbinit
submodules: true
@@ -102,9 +102,13 @@ jobs:
ref: e98323f8a09abd80fc4cbcd74dee023b91a1ec22
repository: palera1n/PongoOS
- name: Install dependencies (brew)
run: |
brew install make
- name: Build
run: |
make
gmake -j$(sysctl -n hw.ncpu)
- name: Prepare upload directory
run: |
@@ -176,7 +180,7 @@ jobs:
- name: Install dependencies (apt)
run: |
sudo apt update
sudo apt install -y build-essential cmake autoconf automake libtool pkg-config zstd
sudo apt install -y build-essential cmake autoconf automake libtool pkg-config zstd jq
- name: Build
run: |
@@ -255,11 +259,11 @@ jobs:
- name: Install dependencies (brew)
run: |
brew update
brew install cmake autoconf automake libtool pkg-config
brew install make cmake autoconf automake libtool pkg-config
- name: Build
run: |
make palera1n WITH_STATIC=1 WITH_GUI=1 WITH_TUI=1 WITH_CIDERRAIN=1 BUILD_TYPE=Release JOBS=$(sysctl -n hw.ncpu)
gmake palera1n WITH_STATIC=1 WITH_GUI=1 WITH_TUI=1 WITH_CIDERRAIN=1 BUILD_TYPE=Release JOBS=$(sysctl -n hw.ncpu)
strip -x build/palera1n.app/Contents/MacOS/palera1n
- name: Package
@@ -304,16 +308,17 @@ jobs:
- name: Install dependencies (brew)
run: |
brew update
brew install cmake libtool gnu-sed
brew install make cmake libtool gnu-sed
- name: Build
run: |
make palera1n_xcode PLATFORM=iphoneos WITH_STATIC=1 BUILD_TYPE=Release JOBS=$(sysctl -n hw.ncpu)
gmake palera1n_xcode PLATFORM=iphoneos WITH_STATIC=1 WITH_CIDERRAIN=1 BUILD_TYPE=Release JOBS=$(sysctl -n hw.ncpu)
cmake --build build
codesign --force --sign - --entitlements resources/entitlements.xml build/Debug-iphoneos/palera1n.app/palera1n
- name: Package
run: |
cd build
cd build
cpack -DCPACK_PACKAGE_FILE_NAME="palera1n-iphoneos-arm" \
-DCPACK_PACKAGING_INSTALL_PREFIX="/usr/"
cpack -DCPACK_PACKAGE_FILE_NAME="palera1n-iphoneos-arm64" \
@@ -432,6 +437,7 @@ jobs:
mingw-w64-x86_64-libusb
mingw-w64-x86_64-rust
mingw-w64-x86_64-nsis
mingw-w64-x86_64-jq
libtool
openssl
openssl-devel
@@ -534,12 +540,12 @@ jobs:
- name: Create Release
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65
with:
name: v${{ steps.get_version.outputs.version }}
tag_name: v${{ steps.get_version.outputs.version }}
name: ${{ steps.get_version.outputs.version }}
tag_name: ${{ steps.get_version.outputs.version }}
files: |
dist/*
generate_release_notes: true
fail_on_unmatched_files: true
draft: true
env:
GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+58 -11
View File
@@ -1,26 +1,41 @@
name: "Upload debs"
on:
workflow_dispatch:
inputs:
version:
description: "palera1n tag"
required: true
type: string
release:
types: [published]
env:
TAG: ${{ github.event.inputs.version || github.event.release.tag_name }}
jobs:
upload:
runs-on: ubuntu-latest
steps:
- name: Download debs from release
- uses: actions/checkout@v4
- name: Download debs from tag
env:
GH_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release download "${{ github.event.release.tag_name }}" \
--pattern "palera1n-iphoneos-arm64.deb" \
--pattern "palera1n-iphoneos-arm.deb"
gh release download "${{ env.TAG }}"
if [ ! -f "palera1n-iphoneos-arm64.deb" ] || [ ! -f "palera1n-iphoneos-arm.deb" ]; then
echo "Debs not found :/"
exit 1
fi
mkdir -p cdn-upload
cp *.tar.gz cdn-upload/
cp *.deb cdn-upload/
cp *.dmg cdn-upload/
- name: Upload debs to repo
if: github.repository == 'palera1n/palera1n'
env:
@@ -28,18 +43,50 @@ jobs:
API_TOKEN: ${{ secrets.BUILD_GITHUB_TOKEN }}
GH_REPO: palera1n/repo.palera.in
run: |
git clone https://$USERNAME:[email protected]/$GH_REPO.git upload
git clone https://$USERNAME:[email protected]/$GH_REPO.git repo-upload
ARM64_HASH=$(sha256sum palera1n-iphoneos-arm64.deb | cut -c1-8)
ARM_HASH=$(sha256sum palera1n-iphoneos-arm.deb | cut -c1-8)
cp palera1n-iphoneos-arm64.deb upload/pool/iphoneos-arm64/palera1n_${{ github.event.release.tag_name }}_${ARM64_HASH}_iphoneos-arm64.deb
cp palera1n-iphoneos-arm.deb upload/pool/iphoneos-arm/palera1n_${{ github.event.release.tag_name }}_${ARM_HASH}_iphoneos-arm.deb
cp palera1n-iphoneos-arm64.deb repo-upload/pool/iphoneos-arm64/palera1n_${{ env.TAG }}_${ARM64_HASH}_iphoneos-arm64.deb
cp palera1n-iphoneos-arm.deb repo-upload/pool/iphoneos-arm/palera1n_${{ env.TAG }}_${ARM_HASH}_iphoneos-arm.deb
cd upload
cd repo-upload
git config user.name "github-actions[bot]"
git config user.name "$USERNAME"
git config user.email "[email protected]"
git add .
git commit -m "Update palera1n for ${{ github.event.release.tag_name }}" || exit 0
git commit -m "Update palera1n for ${{ env.TAG }}" || exit 0
git push https://$USERNAME:[email protected]/$GH_REPO.git
- name: Upload artifacts to cdn
if: github.repository == 'palera1n/palera1n'
uses: wangyucode/sftp-upload-action@v3
with:
host: ${{ secrets.NICKCHAN_FTP_HOST }}
port: ${{ secrets.NICKCHAN_FTP_PORT }}
username: palera1n
password: ${{ secrets.NICKCHAN_FTP_PASS }}
forceUpload: true
dryRun: false
localDir: 'cdn-upload'
remoteDir: "/palera1n/c-rewrite/releases/${{ env.TAG }}"
- name: Bump palen1x
if: github.repository == 'palera1n/palera1n'
env:
USERNAME: GitHub-Actions
API_TOKEN: ${{ secrets.BUILD_GITHUB_TOKEN }}
GH_REPO: palera1n/palen1x
run: |
git clone https://$USERNAME:[email protected]/$GH_REPO.git tag
cd tag
git config --global user.name "$USERNAME"
git config --global user.email "[email protected]"
git commit --allow-empty -m "bump to ${{ env.TAG }}"
git push https://$USERNAME:[email protected]/$GH_REPO.git Alpine
git tag "${{ env.TAG }}"
git push https://$USERNAME:[email protected]/$GH_REPO.git "${{ env.TAG }}"
+1
View File
@@ -8,6 +8,7 @@ embedded/Pongo.bin
embedded/checkra1n-kpf-pongo
embedded/ramdisk.dmg
embedded/binpack.dmg
embedded/DFUHelperDeviceInfo-minified.json
apple-include-*
libusbK/
+30 -327
View File
@@ -25,34 +25,10 @@ option(WITH_CIDERRAIN "Build with Ciderra1n instead of Openra1n" OFF)
# MARK: BUILD REQUIREMENTS
# =========================
if(LINUX AND WITH_STATIC)
if(NOT CROSS_HOST_TRIPLE MATCHES "musl" AND NOT CMAKE_C_COMPILER_TARGET MATCHES "musl" AND NOT CMAKE_C_COMPILER MATCHES "musl")
message(FATAL_ERROR "Static builds on Linux require a musl toolchain. Please specify a musl cross-compiler or set -DCROSS_HOST_TRIPLE=...-linux-musl")
endif()
endif()
if(MINGW AND NOT WITH_STATIC)
message(FATAL_ERROR "MinGW builds must be static. Please configure with -DWITH_STATIC=1")
endif()
if(MINGW AND WITH_TUI)
message(FATAL_ERROR "-DWITH_TUI=1 is not supported on MinGW builds.")
endif()
if(MINGW AND WITH_CIDERRAIN)
message(FATAL_ERROR "-DWITH_CIDERRAIN=1 is not supported on MinGW builds.")
endif()
if(IOS AND (WITH_TUI OR WITH_GUI))
message(FATAL_ERROR "-DWITH_TUI=1 or -DWITH_GUI=1 is not supported on iOS builds.")
endif()
if(IOS AND WITH_CIDERRAIN)
message(FATAL_ERROR "-DWITH_CIDERRAIN=1 is not supported on iOS builds.")
endif()
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/BuildRequirements.cmake")
# =========================
# SETUP
# MARK: SETUP
# =========================
if(MINGW)
@@ -164,33 +140,7 @@ if(WITH_CIDERRAIN)
target_compile_definitions(palera1n PRIVATE WITH_CIDERRAIN)
endif()
execute_process(
COMMAND git rev-parse HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND git rev-parse --abbrev-ref --symbolic-full-name "@{u}"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
execute_process(
COMMAND git remote get-url origin
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_URL
OUTPUT_STRIP_TRAILING_WHITESPACE
)
target_compile_definitions(palera1n PRIVATE
GIT_HASH="${GIT_HASH}"
GIT_BRANCH="${GIT_BRANCH}"
GIT_URL="${GIT_URL}"
)
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/Git.cmake")
# =========================
# MARK: LINKS
@@ -208,225 +158,24 @@ if(WIN32)
endif()
# =========================
# MARK: NON-CMAKE DEPENDENCIES
# MARK: NON-CMAKE DEPENDENCIES (LOCAL)
# =========================
# ra1ns
if(WITH_CIDERRAIN)
message(STATUS "Building with Ciderra1n support")
# TODO: get rid
execute_process(
COMMAND patch --batch --forward -p1 -i ${CMAKE_SOURCE_DIR}/patches/liteusb/0001-cpp-compatible.patch
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/1stparty/libciderra1n/external/liteusb
RESULT_VARIABLE LITEUSB_PATCH_RESULT
)
if(IOS)
execute_process(
COMMAND xcrun --sdk iphoneos --show-sdk-path
OUTPUT_VARIABLE IOS_SDK
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E env
"CFLAGS=-isysroot ${IOS_SDK} -arch arm64 -miphoneos-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -I${CMAKE_SOURCE_DIR}/apple-include-iphoneos"
"CXXFLAGS=-isysroot ${IOS_SDK} -arch arm64 -miphoneos-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -I${CMAKE_SOURCE_DIR}/apple-include-iphoneos"
"LDFLAGS=-isysroot ${IOS_SDK} -arch arm64 -miphoneos-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}"
make CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} AR=${CMAKE_AR}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/1stparty/libciderra1n
RESULT_VARIABLE CIDERRA1N_BUILD_RESULT
)
else()
execute_process(
COMMAND make CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/1stparty/libciderra1n
RESULT_VARIABLE CIDERRA1N_BUILD_RESULT
)
endif()
if(NOT CIDERRA1N_BUILD_RESULT EQUAL 0)
message(FATAL_ERROR "Failed to build Ciderra1n.")
endif()
set(CIDERRAIN_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/1stparty/libciderra1n/build/include")
set(CIDERRAIN_LIB "${CMAKE_SOURCE_DIR}/1stparty/libciderra1n/build/lib/ciderra1n/libciderra1n.a")
target_include_directories(palera1n PRIVATE ${CIDERRAIN_INCLUDE_DIR})
target_link_libraries(palera1n PRIVATE "${CIDERRAIN_LIB}")
if(IOS)
target_include_directories(palera1n PRIVATE "${CMAKE_SOURCE_DIR}/apple-include-iphoneos")
endif()
if(LINUX)
set(LITEUSB_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/1stparty/libciderra1n/external/liteusb/include")
target_compile_definitions(palera1n PRIVATE LITEUSB_PLATFORM_LINUX)
target_include_directories(palera1n PRIVATE ${LITEUSB_INCLUDE_DIR})
endif()
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/Ciderra1n.cmake")
else()
message(STATUS "Building with Openra1n support")
if(IOS)
execute_process(
COMMAND xcrun --sdk iphoneos --show-sdk-path
OUTPUT_VARIABLE IOS_SDK
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E env
"CFLAGS=-isysroot ${IOS_SDK} -arch arm64 -miphoneos-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -I${CMAKE_SOURCE_DIR}/apple-include-iphoneos"
"CXXFLAGS=-isysroot ${IOS_SDK} -arch arm64 -miphoneos-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -I${CMAKE_SOURCE_DIR}/apple-include-iphoneos"
"LDFLAGS=-isysroot ${IOS_SDK} -arch arm64 -miphoneos-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}"
make CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} AR=${CMAKE_AR}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/1stparty/libopenra1n
RESULT_VARIABLE OPENRA1N_BUILD_RESULT
)
else()
execute_process(
COMMAND make CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/1stparty/libopenra1n
RESULT_VARIABLE OPENRA1N_BUILD_RESULT
)
endif()
if(NOT OPENRA1N_BUILD_RESULT EQUAL 0)
message(FATAL_ERROR "Failed to build Openra1n.")
endif()
set(OPENRA1N_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/1stparty/libopenra1n/build/include")
set(OPENRA1N_LIB "${CMAKE_SOURCE_DIR}/1stparty/libopenra1n/build/lib/openra1n/libopenra1n.a")
target_include_directories(palera1n PRIVATE ${OPENRA1N_INCLUDE_DIR})
target_link_libraries(palera1n PRIVATE "${OPENRA1N_LIB}")
if(IOS)
target_include_directories(palera1n PRIVATE "${CMAKE_SOURCE_DIR}/apple-include-iphoneos")
endif()
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/Openra1n.cmake")
endif()
# idevice
if(WITH_GUI OR WITH_TUI)
set(IDevice_CARGO_ARGS
--release
--no-default-features
--features "usbmuxd ring tcp"
)
set(IDevice_ENV)
if(CROSS_HOST_TRIPLE)
if(CROSS_HOST_TRIPLE STREQUAL "i486-linux-musl")
set(RUST_TARGET "i686-unknown-linux-musl")
elseif(CROSS_HOST_TRIPLE STREQUAL "x86_64-linux-musl")
set(RUST_TARGET "x86_64-unknown-linux-musl")
elseif(CROSS_HOST_TRIPLE STREQUAL "armel-linux-musleabi")
set(RUST_TARGET "arm-unknown-linux-musleabi")
elseif(CROSS_HOST_TRIPLE STREQUAL "aarch64-linux-musl")
set(RUST_TARGET "aarch64-unknown-linux-musl")
endif()
if(RUST_TARGET)
string(TOUPPER "${RUST_TARGET}" RUST_TARGET_ENV)
string(REPLACE "-" "_" RUST_TARGET_ENV "${RUST_TARGET_ENV}")
list(APPEND IDevice_CARGO_ARGS --target ${RUST_TARGET})
list(APPEND IDevice_ENV
"CC=${CMAKE_C_COMPILER}"
"AR=${CMAKE_AR}"
"CARGO_TARGET_${RUST_TARGET_ENV}_LINKER=${CMAKE_C_COMPILER}"
)
endif()
elseif(MINGW)
set(RUST_TARGET "x86_64-pc-windows-gnu")
list(APPEND IDevice_CARGO_ARGS --target ${RUST_TARGET})
list(APPEND IDevice_ENV
"CC=${CMAKE_C_COMPILER}"
"AR=${CMAKE_AR}"
"CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=${CMAKE_C_COMPILER}"
)
endif()
ExternalProject_Add(idevice_ep
GIT_REPOSITORY https://github.com/jkcoxson/idevice.git
GIT_TAG v0.1.65
PATCH_COMMAND
patch --forward --ignore-whitespace -p1 < "${CMAKE_SOURCE_DIR}/patches/idevice/0001-compile-usbmuxd-and-windows-fixes.patch" || true
CONFIGURE_COMMAND ""
BUILD_COMMAND
${CMAKE_COMMAND} -E env
${IDevice_ENV}
cargo build
${IDevice_CARGO_ARGS}
--manifest-path <SOURCE_DIR>/ffi/Cargo.toml
COMMAND ${CMAKE_COMMAND} -E chdir <SOURCE_DIR>/cpp
${CMAKE_COMMAND}
-B build
-DCMAKE_BUILD_TYPE=Release
-DIDEVICE_FFI_PATH=<SOURCE_DIR>/target/${RUST_TARGET}/release/${FFI_LIB_NAME}
"-DCMAKE_CXX_FLAGS=-Du_int64_t=uint64_t -Du_int32_t=uint32_t -Du_int16_t=uint16_t -Du_int8_t=uint8_t"
COMMAND ${CMAKE_COMMAND} --build <SOURCE_DIR>/cpp/build --config Release
INSTALL_COMMAND
${CMAKE_COMMAND} -E make_directory <INSTALL_DIR>/lib/idevice
COMMAND ${CMAKE_COMMAND} -E make_directory <INSTALL_DIR>/include
COMMAND ${CMAKE_COMMAND} -E copy
<SOURCE_DIR>/target/${RUST_TARGET}/release/libidevice_ffi.a
<INSTALL_DIR>/lib/idevice/libidevice_ffi.a
COMMAND ${CMAKE_COMMAND} -E copy
<SOURCE_DIR>/cpp/build/libidevice++.a
<INSTALL_DIR>/lib/idevice/libidevice++.a
COMMAND ${CMAKE_COMMAND} -E copy_directory
<SOURCE_DIR>/cpp/include
<INSTALL_DIR>/include
BUILD_IN_SOURCE 1
)
ExternalProject_Get_Property(idevice_ep install_dir)
set(IDEVICE_INCLUDE_DIR "${install_dir}/include")
set(IDEVICE_LIBRARY "${install_dir}/lib/idevice/libidevice++.a")
set(IDEVICE_FFI_LIBRARY "${install_dir}/lib/idevice/libidevice_ffi.a")
add_dependencies(palera1n idevice_ep)
target_include_directories(palera1n PRIVATE ${IDEVICE_INCLUDE_DIR})
target_link_libraries(palera1n PRIVATE "${IDEVICE_LIBRARY}" "${IDEVICE_FFI_LIBRARY}")
if(MINGW)
target_link_libraries(palera1n PRIVATE bcrypt userenv ntdll)
endif()
target_compile_definitions(palera1n PRIVATE LIBPLIST_STATIC)
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/Idevice.cmake")
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Release")
if(APPLE)
target_link_options(palera1n PRIVATE
-Wl,-dead_strip
-Wl,-x
)
elseif(MINGW)
target_link_options(palera1n PRIVATE
-Wl,--gc-sections
-Wl,--strip-all
)
elseif(LINUX)
target_link_options(palera1n PRIVATE
-Wl,--gc-sections
-Wl,--strip-all
)
endif()
endif()
# =========================
# MARK: NON-CMAKE DEPENDENCIES
# =========================
if(WITH_STATIC)
find_program(PKG_CONFIG_EXECUTABLE NAMES pkg-config)
@@ -596,77 +345,31 @@ else()
endif()
# =========================
# MARK: INSTALL
# MARK: STRIP FLAGS
# =========================
if(LINUX AND NOT MINGW)
install(TARGETS palera1n RUNTIME DESTINATION bin)
elseif(IOS)
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/Debug-iphoneos/palera1n.app/palera1n" DESTINATION bin)
elseif(APPLE AND WITH_GUI)
install(TARGETS palera1n BUNDLE DESTINATION .)
elseif(APPLE)
install(TARGETS palera1n RUNTIME DESTINATION bin)
elseif(MINGW)
install(TARGETS palera1n
RUNTIME DESTINATION .
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/libstdc++-6.dll"
"${CMAKE_CURRENT_BINARY_DIR}/libgcc_s_seh-1.dll"
"${CMAKE_CURRENT_BINARY_DIR}/libwinpthread-1.dll"
DESTINATION .
)
if(NOT WITH_CIDERRAIN)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/libusb-1.0.dll"
DESTINATION .
if(CMAKE_BUILD_TYPE STREQUAL "Release")
if(APPLE)
target_link_options(palera1n PRIVATE
-Wl,-dead_strip
-Wl,-x
)
elseif(MINGW)
target_link_options(palera1n PRIVATE
-Wl,--gc-sections
-Wl,--strip-all
)
elseif(LINUX)
target_link_options(palera1n PRIVATE
-Wl,--gc-sections
-Wl,--strip-all
)
endif()
endif()
if((LINUX AND NOT MINGW) OR IOS OR (APPLE AND NOT IOS AND NOT WITH_GUI))
install(FILES "${CMAKE_SOURCE_DIR}/docs/palera1n.1" DESTINATION share/man/man1)
install(FILES "${CMAKE_SOURCE_DIR}/docs/p1ctl.8" DESTINATION share/man/man8)
endif()
# =========================
# MARK: INSTALL
# =========================
set(CPACK_PACKAGE_NAME "palera1n")
set(CPACK_PACKAGE_VERSION "0")
set(CPACK_PACKAGE_FILE_NAME "palera1n")
if(MINGW)
set(CPACK_GENERATOR "NSIS64")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "palera1n")
set(CPACK_NSIS_DISPLAY_NAME "palera1n")
set(CPACK_NSIS_PACKAGE_NAME "palera1n")
set(CPACK_NSIS_BRANDING_TEXT "palera1n Setup")
set(CPACK_NSIS_MODIFY_PATH OFF)
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/resources/palera1n.ico")
set(CPACK_NSIS_MUI_UNIICON "${CMAKE_SOURCE_DIR}/resources/palera1n.ico")
set(CPACK_PACKAGE_EXECUTABLES "palera1n" "palera1n")
set(CPACK_NSIS_CREATE_ICONS_EXTRA
"CreateShortCut \\\"\\$DESKTOP\\\\palera1n.lnk\\\" \\\"\\$INSTDIR\\\\bin\\\\palera1n.exe\\\""
)
set(CPACK_NSIS_DELETE_ICONS_EXTRA
"Delete \\\"\\$DESKTOP\\\\palera1n.lnk\\\""
)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
elseif(APPLE AND WITH_GUI)
set(CPACK_GENERATOR "DragNDrop")
else()
set(CPACK_PACKAGING_INSTALL_PREFIX "/")
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)
set(CPACK_GENERATOR "TGZ")
endif()
include(CPack)
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/BuildInstall.cmake")
+8 -2
View File
@@ -34,6 +34,7 @@ ifeq ($(PLATFORM),iphoneos)
ifneq ($(UNAME_S),Darwin)
$(error iOS builds require macOS/Xcode)
endif
EXTRA_TARGETS = apple-include
TARGET_SYSROOT := $(shell xcrun --sdk iphoneos --show-sdk-path)
else ifeq ($(PLATFORM),macos)
ifneq ($(UNAME_S),Darwin)
@@ -79,6 +80,8 @@ else
APPLE_INCLUDE_DEP :=
endif
all: palera1n
apple-include:
mkdir -p $(CUSTOM_INCLUDE_PATH)/{bsm,objc,os/internal,sys,firehose,CoreFoundation,FSEvents,IOSurface,IOKit/kext,libkern,kern,arm,{mach/,}machine,CommonCrypto,Security,CoreSymbolication,Kernel/{kern,IOKit,libkern},rpc,rpcsvc,xpc/private,ktrace,mach-o,dispatch}
cp -af $(MACOSX_SYSROOT)/usr/include/{arpa,bsm,hfs,net,xpc,netinet,servers,timeconv.h,launch.h} $(CUSTOM_INCLUDE_PATH)
@@ -114,8 +117,9 @@ apple-include:
payloads:
mkdir -p src/gen/embedded
xz --format=lzma -vfc6ekT 0 embedded/ramdisk.dmg > embedded/ramdisk-compressed.dmg.lzma
xz --format=lzma -vfc6ekT 0 embedded/ramdisk.dmg > embedded/ramdisk-compressed.lzma
xz --format=lzma -vfc6ekT 0 embedded/checkra1n-kpf-pongo > embedded/checkra1n-kpf-pongo-compressed.lzma
jq -c . embedded/DFUHelperDeviceInfo.json > embedded/DFUHelperDeviceInfo-minified.json
@for file in embedded/*; do \
name=$$(basename "$$file"); \
@@ -128,7 +132,7 @@ payloads:
>> "src/gen/embedded/$$name.h"; \
done
palera1n: payloads
palera1n: payloads $(EXTRA_TARGETS)
@cmake -S . -B build \
$(CMAKE_COMMON_ARGS) \
$(CMAKE_APPLE_ARGS) && \
@@ -151,3 +155,5 @@ clean:
@rm -rf apple-include-*
@if [ -d 1stparty/libciderra1n ]; then $(MAKE) -C 1stparty/libciderra1n clean; fi
@$(MAKE) -C 1stparty/libopenra1n clean
.PHONY: palera1n palera1n_xcode palera1n_mingw payloads clean
+1 -1
View File
@@ -171,7 +171,7 @@ make palera1n_mingw
- [staturnz](https://github.com/staturnz) - Liteusb, Loader contributions
- [libusb](https://github.com/libimobiledevice/libimobiledevice) - Library for access to usb-devices, used by libopenra1n
- [idevice](https://github.com/jkcoxson/idevice) - Library for access to usbmuxd devices
- [plooshi](https://github.com/plooshi) - Plooshfinder, plooshinit, various legacy patches
- [sarah](https://github.com/plooshi) - Plooshfinder, plooshinit, various legacy patches
- [Procursus](https://github.com/ProcursusTeam/Procursus) - Bootstrap & binpack
- [tealbathingsuit](https://github.com/tealbathingsuit) - Tweak injection ([ElleKit](https://github.com/tealbathingsuit/ellekit))
- [sbingner](https://github.com/sbingner) - Substitute
+74
View File
@@ -0,0 +1,74 @@
# =========================
# MARK: INSTALL
# =========================
if(LINUX AND NOT MINGW)
install(TARGETS palera1n RUNTIME DESTINATION bin)
elseif(IOS)
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/Debug-iphoneos/palera1n.app/palera1n" DESTINATION bin)
elseif(APPLE AND WITH_GUI)
install(TARGETS palera1n BUNDLE DESTINATION .)
elseif(APPLE)
install(TARGETS palera1n RUNTIME DESTINATION bin)
elseif(MINGW)
install(TARGETS palera1n
RUNTIME DESTINATION .
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/libstdc++-6.dll"
"${CMAKE_CURRENT_BINARY_DIR}/libgcc_s_seh-1.dll"
"${CMAKE_CURRENT_BINARY_DIR}/libwinpthread-1.dll"
DESTINATION .
)
if(NOT WITH_CIDERRAIN)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/libusb-1.0.dll"
DESTINATION .
)
endif()
endif()
if((LINUX AND NOT MINGW) OR IOS OR (APPLE AND NOT IOS AND NOT WITH_GUI))
install(FILES "${CMAKE_SOURCE_DIR}/docs/palera1n.1" DESTINATION share/man/man1)
install(FILES "${CMAKE_SOURCE_DIR}/docs/p1ctl.8" DESTINATION share/man/man8)
endif()
set(CPACK_PACKAGE_NAME "palera1n")
set(CPACK_PACKAGE_VERSION "0")
set(CPACK_PACKAGE_FILE_NAME "palera1n")
if(MINGW)
set(CPACK_GENERATOR "NSIS64")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "palera1n")
set(CPACK_NSIS_DISPLAY_NAME "palera1n")
set(CPACK_NSIS_PACKAGE_NAME "palera1n")
set(CPACK_NSIS_BRANDING_TEXT "palera1n Setup")
set(CPACK_NSIS_MODIFY_PATH OFF)
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/resources/palera1n.ico")
set(CPACK_NSIS_MUI_UNIICON "${CMAKE_SOURCE_DIR}/resources/palera1n.ico")
set(CPACK_PACKAGE_EXECUTABLES "palera1n" "palera1n")
set(CPACK_NSIS_CREATE_ICONS_EXTRA
"CreateShortCut \\\"\\$DESKTOP\\\\palera1n.lnk\\\" \\\"\\$INSTDIR\\\\bin\\\\palera1n.exe\\\""
)
set(CPACK_NSIS_DELETE_ICONS_EXTRA
"Delete \\\"\\$DESKTOP\\\\palera1n.lnk\\\""
)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
elseif(APPLE AND WITH_GUI)
set(CPACK_GENERATOR "DragNDrop")
else()
set(CPACK_PACKAGING_INSTALL_PREFIX "/")
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)
set(CPACK_GENERATOR "TGZ")
endif()
include(CPack)
+41
View File
@@ -0,0 +1,41 @@
# =========================
# BUILD REQUIREMENTS
# =========================
if(LINUX AND WITH_STATIC)
if(
NOT CROSS_HOST_TRIPLE MATCHES "musl"
AND NOT CMAKE_C_COMPILER_TARGET MATCHES "musl"
AND NOT CMAKE_C_COMPILER MATCHES "musl"
)
message(FATAL_ERROR
"Static builds on Linux require a musl toolchain. "
"Please specify a musl cross-compiler or set "
"-DCROSS_HOST_TRIPLE=...-linux-musl"
)
endif()
endif()
if(MINGW AND NOT WITH_STATIC)
message(FATAL_ERROR
"MinGW builds must be static. Please configure with -DWITH_STATIC=1"
)
endif()
if(MINGW AND WITH_TUI)
message(FATAL_ERROR
"-DWITH_TUI=1 is not supported on MinGW builds."
)
endif()
if(MINGW AND WITH_CIDERRAIN)
message(FATAL_ERROR
"-DWITH_CIDERRAIN=1 is not supported on MinGW builds."
)
endif()
if(IOS AND (WITH_TUI OR WITH_GUI))
message(FATAL_ERROR
"-DWITH_TUI=1 or -DWITH_GUI=1 is not supported on iOS builds."
)
endif()
+61
View File
@@ -0,0 +1,61 @@
# =========================
# MARK: NON-CMAKE DEPENDENCIES: CIDERRAIN
# =========================
message(STATUS "Building with Ciderra1n support")
# TODO: get rid
execute_process(
COMMAND patch --batch --forward -p1 -i ${CMAKE_SOURCE_DIR}/patches/liteusb/0001-cpp-compatible.patch
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/1stparty/libciderra1n/external/liteusb
RESULT_VARIABLE LITEUSB_PATCH_RESULT
)
if(IOS)
execute_process(
COMMAND xcrun --sdk iphoneos --show-sdk-path
OUTPUT_VARIABLE IOS_SDK
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E env
"EXTRA_CFLAGS=-isysroot ${IOS_SDK} -arch arm64 -miphoneos-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -I${CMAKE_SOURCE_DIR}/apple-include-iphoneos"
"CXXFLAGS=-isysroot ${IOS_SDK} -arch arm64 -miphoneos-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -I${CMAKE_SOURCE_DIR}/apple-include-iphoneos"
"LDFLAGS=-isysroot ${IOS_SDK} -arch arm64 -miphoneos-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}"
make CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} AR=${CMAKE_AR}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/1stparty/libciderra1n
RESULT_VARIABLE CIDERRA1N_BUILD_RESULT
)
elseif(APPLE)
execute_process(
COMMAND make CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} EXTRA_CFLAGS=-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/1stparty/libciderra1n
RESULT_VARIABLE CIDERRA1N_BUILD_RESULT
)
else()
execute_process(
COMMAND make CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/1stparty/libciderra1n
RESULT_VARIABLE CIDERRA1N_BUILD_RESULT
)
endif()
if(NOT CIDERRA1N_BUILD_RESULT EQUAL 0)
message(FATAL_ERROR "Failed to build Ciderra1n.")
endif()
set(CIDERRAIN_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/1stparty/libciderra1n/build/include")
set(CIDERRAIN_LIB "${CMAKE_SOURCE_DIR}/1stparty/libciderra1n/build/lib/ciderra1n/libciderra1n.a")
target_include_directories(palera1n PRIVATE ${CIDERRAIN_INCLUDE_DIR})
target_link_libraries(palera1n PRIVATE "${CIDERRAIN_LIB}")
if(IOS)
target_include_directories(palera1n PRIVATE "${CMAKE_SOURCE_DIR}/apple-include-iphoneos")
endif()
if(LINUX)
set(LITEUSB_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/1stparty/libciderra1n/external/liteusb/include")
target_compile_definitions(palera1n PRIVATE LITEUSB_PLATFORM_LINUX)
target_include_directories(palera1n PRIVATE ${LITEUSB_INCLUDE_DIR})
endif()
+31
View File
@@ -0,0 +1,31 @@
# =========================
# MARK: GIT INFO
# =========================
execute_process(
COMMAND git rev-parse HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND git rev-parse --abbrev-ref --symbolic-full-name "@{u}"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
execute_process(
COMMAND git remote get-url origin
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_URL
OUTPUT_STRIP_TRAILING_WHITESPACE
)
target_compile_definitions(palera1n PRIVATE
GIT_HASH="${GIT_HASH}"
GIT_BRANCH="${GIT_BRANCH}"
GIT_URL="${GIT_URL}"
)
+121
View File
@@ -0,0 +1,121 @@
# =========================
# MARK: NON-CMAKE DEPENDENCIES: IDEVICE
# =========================
set(IDevice_CARGO_ARGS
--release
--no-default-features
--features "usbmuxd ring tcp"
)
set(IDevice_ENV)
if(APPLE)
if(IOS)
list(APPEND IDevice_ENV "IPHONEOS_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
else()
list(APPEND IDevice_ENV "MACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
endif()
endif()
if(CROSS_HOST_TRIPLE)
if(CROSS_HOST_TRIPLE STREQUAL "i486-linux-musl")
set(RUST_TARGET "i686-unknown-linux-musl")
elseif(CROSS_HOST_TRIPLE STREQUAL "x86_64-linux-musl")
set(RUST_TARGET "x86_64-unknown-linux-musl")
elseif(CROSS_HOST_TRIPLE STREQUAL "armel-linux-musleabi")
set(RUST_TARGET "arm-unknown-linux-musleabi")
elseif(CROSS_HOST_TRIPLE STREQUAL "aarch64-linux-musl")
set(RUST_TARGET "aarch64-unknown-linux-musl")
endif()
if(RUST_TARGET)
string(TOUPPER "${RUST_TARGET}" RUST_TARGET_ENV)
string(REPLACE "-" "_" RUST_TARGET_ENV "${RUST_TARGET_ENV}")
list(APPEND IDevice_CARGO_ARGS --target ${RUST_TARGET})
list(APPEND IDevice_ENV
"CC=${CMAKE_C_COMPILER}"
"AR=${CMAKE_AR}"
"CARGO_TARGET_${RUST_TARGET_ENV}_LINKER=${CMAKE_C_COMPILER}"
)
endif()
elseif(MINGW)
set(RUST_TARGET "x86_64-pc-windows-gnu")
list(APPEND IDevice_CARGO_ARGS --target ${RUST_TARGET})
list(APPEND IDevice_ENV
"CC=${CMAKE_C_COMPILER}"
"AR=${CMAKE_AR}"
"CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=${CMAKE_C_COMPILER}"
)
endif()
# Only build idevice if libraries are missing
set(IDEVICE_INSTALL_DIR "${CMAKE_BINARY_DIR}/idevice_ep-prefix")
if(NOT (EXISTS "${IDEVICE_INSTALL_DIR}/lib/idevice/libidevice++.a"
AND EXISTS "${IDEVICE_INSTALL_DIR}/lib/idevice/libidevice_ffi.a"))
ExternalProject_Add(idevice_ep
GIT_REPOSITORY https://github.com/jkcoxson/idevice.git
GIT_TAG v0.1.65
PATCH_COMMAND
patch --forward --ignore-whitespace -p1 < "${CMAKE_SOURCE_DIR}/patches/idevice/0001-compile-usbmuxd-and-windows-fixes.patch" || true
CONFIGURE_COMMAND ""
BUILD_COMMAND
${CMAKE_COMMAND} -E env
${IDevice_ENV}
cargo build
${IDevice_CARGO_ARGS}
--manifest-path <SOURCE_DIR>/ffi/Cargo.toml
COMMAND ${CMAKE_COMMAND} -E chdir <SOURCE_DIR>/cpp
${CMAKE_COMMAND}
-B build
-DCMAKE_BUILD_TYPE=Release
-DIDEVICE_FFI_PATH=<SOURCE_DIR>/target/${RUST_TARGET}/release/${FFI_LIB_NAME}
"-DCMAKE_CXX_FLAGS=-Du_int64_t=uint64_t -Du_int32_t=uint32_t -Du_int16_t=uint16_t -Du_int8_t=uint8_t"
"-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}"
COMMAND ${CMAKE_COMMAND} --build <SOURCE_DIR>/cpp/build --config Release
INSTALL_COMMAND
${CMAKE_COMMAND} -E make_directory <INSTALL_DIR>/lib/idevice
COMMAND ${CMAKE_COMMAND} -E make_directory <INSTALL_DIR>/include
COMMAND ${CMAKE_COMMAND} -E copy
<SOURCE_DIR>/target/${RUST_TARGET}/release/libidevice_ffi.a
<INSTALL_DIR>/lib/idevice/libidevice_ffi.a
COMMAND ${CMAKE_COMMAND} -E copy
<SOURCE_DIR>/cpp/build/libidevice++.a
<INSTALL_DIR>/lib/idevice/libidevice++.a
COMMAND ${CMAKE_COMMAND} -E copy_directory
<SOURCE_DIR>/cpp/include
<INSTALL_DIR>/include
BUILD_IN_SOURCE 1
)
add_dependencies(palera1n idevice_ep)
endif()
set(IDEVICE_INCLUDE_DIR "${IDEVICE_INSTALL_DIR}/include")
set(IDEVICE_LIBRARY "${IDEVICE_INSTALL_DIR}/lib/idevice/libidevice++.a")
set(IDEVICE_FFI_LIBRARY "${IDEVICE_INSTALL_DIR}/lib/idevice/libidevice_ffi.a")
target_include_directories(palera1n PRIVATE ${IDEVICE_INCLUDE_DIR})
target_link_libraries(palera1n PRIVATE "${IDEVICE_LIBRARY}" "${IDEVICE_FFI_LIBRARY}")
if(MINGW)
target_link_libraries(palera1n PRIVATE bcrypt userenv ntdll)
endif()
target_compile_definitions(palera1n PRIVATE LIBPLIST_STATIC)
+51
View File
@@ -0,0 +1,51 @@
# =========================
# MARK: NON-CMAKE DEPENDENCIES: OPENRAIN
# =========================
message(STATUS "Building with Openra1n support")
if(IOS)
execute_process(
COMMAND xcrun --sdk iphoneos --show-sdk-path
OUTPUT_VARIABLE IOS_SDK
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E env
"CFLAGS=-isysroot ${IOS_SDK} -arch arm64 -miphoneos-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -I${CMAKE_SOURCE_DIR}/apple-include-iphoneos"
"CXXFLAGS=-isysroot ${IOS_SDK} -arch arm64 -miphoneos-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -I${CMAKE_SOURCE_DIR}/apple-include-iphoneos"
"LDFLAGS=-isysroot ${IOS_SDK} -arch arm64 -miphoneos-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}"
make CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} AR=${CMAKE_AR}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/1stparty/libopenra1n
RESULT_VARIABLE OPENRA1N_BUILD_RESULT
)
elseif(APPLE)
execute_process(
COMMAND ${CMAKE_COMMAND} -E env
"CFLAGS=-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}"
make CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/1stparty/libopenra1n
RESULT_VARIABLE OPENRA1N_BUILD_RESULT
)
else()
execute_process(
COMMAND make CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/1stparty/libopenra1n
RESULT_VARIABLE OPENRA1N_BUILD_RESULT
)
endif()
if(NOT OPENRA1N_BUILD_RESULT EQUAL 0)
message(FATAL_ERROR "Failed to build Openra1n.")
endif()
set(OPENRA1N_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/1stparty/libopenra1n/build/include")
set(OPENRA1N_LIB "${CMAKE_SOURCE_DIR}/1stparty/libopenra1n/build/lib/openra1n/libopenra1n.a")
target_include_directories(palera1n PRIVATE ${OPENRA1N_INCLUDE_DIR})
target_link_libraries(palera1n PRIVATE "${OPENRA1N_LIB}")
if(IOS)
target_include_directories(palera1n PRIVATE "${CMAKE_SOURCE_DIR}/apple-include-iphoneos")
endif()
+22 -8
View File
@@ -9,7 +9,7 @@
.Nd arm64 iOS/iPadOS/tvOS 15-26, bridgeOS 5-10 jailbreaking tool
.Sh SYNOPSIS
.Nm
.Op Fl hvlfcBsTVpednq
.Op Fl hvlfcBsTVpPednq
.Op Fl e Ar Boot arguments
.Op Fl k Ar Pongo image
.Op Fl o Ar overlay file
@@ -159,6 +159,12 @@ Remove the jailbreak while keeping user data. Some jailbreak files may remain
after running this command. Additionally, jailbreak apps may remain on the
home screen on for a while even when the files are deleted as the icon cache
still has their icons. When used with
.Fl f , -rootful ,
this will actually boot the device in rootless mode then delete the jailbreak
files. As a result, using the loader app to install the jailbreak environment
is not supported when this option is used together with
.Fl f , -rootful
\[char46]
.It Fl -force-enable-ssv
Force the jailbreak to detect Signed System Volume (SSV) as being required on
@@ -174,13 +180,6 @@ option is specified as well.
(It is technically possible to setup fakefs using this option as well, but this
is not a supported scenario)
.Fl f , -rootful ,
this will actually boot the device in rootless mode then delete the jailbreak
files. As a result, using the loader app to install the jailbreak environment
is not supported when this option is used together with
.Fl f , -rootful
\[char46]
.It Fl l , -rootless
Proceed in rootless mode. This option is only supported on iOS/iPadOS.
@@ -219,6 +218,9 @@ Boots the device in verbose mode, allowing boot logs to be seen.
.It Fl p , -early-exit
Exit after booting into a clean PongoOS shell.
.It Fl P , -late-exit
Exit after uploading existing images into the PongoOS shell.
.It Fl e , -extra-bootargs Ar boot arguments
Specify custom XNU kernel command line. Additionally, the
.Em wdt=-1
@@ -372,6 +374,11 @@ Equivalent to using the
.Fl p , -early-exit
option.
.It Ev RA1N_LATE_EXIT
Equivalent to using the
.Fl P , -late-exit
option.
.It Ev RA1N_EXTRA_BOOTARGS
Equivalent to using the
.Fl e , -extra-bootargs
@@ -600,6 +607,13 @@ has been removed, since it leaks memory in launchd.
has been renamed to
.Fl f, -rootful
due to its ambiguity. As it supports both fakefs and realfs on certain platforms.
.Fl P, -pongo-full
has been renamed to
.Fl P, -late-exit
due to its ambiguity.
.Sh SEE ALSO
.Xr launchd 8
.Xr launchd.plist 5
+31 -2
View File
@@ -2,15 +2,19 @@
"devicemap":{
"iPhone6,1":"iphonese",
"iPhone6,2":"iphonese",
"iPhone7,1":"iphone6s",
"iPhone7,2":"iphone6s",
"iPhone8,1":"iphone6s",
"iPhone8,2":"iphone6s",
"iPhone8,4":"iphonese",
"iPhone9,1":"iphone7",
"iPhone9,2":"iphone7",
"iPhone9,3":"iphone7",
"iPhone9,4":"iphone7",
"iPhone10,1":"iphone8",
"iPhone10,2":"iphone8",
"iPhone10,4":"iphone8",
@@ -46,7 +50,6 @@
"iPad7,6":"ipad",
"iPad7,11":"ipad",
"iPad7,12":"ipad",
"iPad8,1":"ipad",
"iPad8,2":"ipad",
"iPad8,3":"ipad",
@@ -72,10 +75,33 @@
"iPad4,9":"ipadmini",
"iPad5,1":"ipadmini",
"iPad5,2":"ipadmini",
"iPod7,1":"ipodtouch",
"iPod9,1":"ipodtouch7",
"AppleTV5,3":"appletv4",
"AppleTV6,2":"appletv4k"
"AppleTV6,2":"appletv4k",
"iMac20,1":"dfuonly",
"iMac20,2":"dfuonly",
"MacBookAir8,1":"dfuonly",
"MacBookAir8,2":"dfuonly",
"MacBookPro9,1":"dfuonly",
"MacBookPro15,1":"dfuonly",
"MacBookPro15,2":"dfuonly",
"MacBookPro15,3":"dfuonly",
"MacBookPro15,4":"dfuonly",
"MacBookPro16,1":"dfuonly",
"MacBookPro16,2":"dfuonly",
"MacBookPro16,3":"dfuonly",
"MacBookPro16,4":"dfuonly",
"iMacPro1,1":"dfuonly",
"Macmini8,1":"dfuonly",
"MacPro7,1":"dfuonly",
"iBridge2,11":"dfuonly",
"iBridge2,13":"dfuonly",
"AudioAccessory1,1":"dfuonly",
"AudioAccessory1,2":"dfuonly"
},
"devicelayout":{
"ipodtouch7":{
@@ -271,6 +297,9 @@
}
},
"sequence":"atv_standard_breakout"
},
"dfuonly": {
"is_supported": false
}
},
"sequences":{
+51 -10
View File
@@ -48,6 +48,8 @@ prefix_path="${XDG_BIN_HOME:-$HOME/.local}"
bin_path="$prefix_path/bin"
install_path="$bin_path/palera1n"
old_install_path="/usr/local/bin/palera1n"
# DMG shit
downloaded_dmg="0"
download() {
local url="$1"
@@ -230,15 +232,44 @@ esac
# Run
# =========
download_version=$(curl -s https://api.github.com/repos/palera1n/palera1n/releases/latest | grep -o '"tag_name": "[^"]*' | sed 's/"tag_name": "//' || true)
latest_tag=$(curl -fsSL https://api.github.com/repos/palera1n/palera1n/tags \
| grep -m1 -o '"name": "[^"]*' \
| sed 's/"name": "//' || true)
if [ -z "$download_version" ]; then
error "Could not retrieve the latest release version from GitHub API."
latest_release=$(curl -fsSL https://api.github.com/repos/palera1n/palera1n/releases/latest \
| grep -o '"tag_name": "[^"]*' \
| sed 's/"tag_name": "//' || true)
if [ -z "$latest_release" ]; then
error "Could not retrieve the latest release version from GitHub."
exit 1
fi
if [ -n "$latest_tag" ] && [ "$latest_tag" != "$latest_release" ]; then
printf "Select a version to download:\n"
printf " 1) Latest Beta (%s)\n" "$latest_tag"
printf " 2) Latest Release (%s)\n" "$latest_release"
printf "Choice [1/2, default: 2]: "
read -r choice
case "$choice" in
1)
download_version="$latest_tag"
;;
""|2)
download_version="$latest_release"
;;
*)
error "Invalid selection."
exit 1
;;
esac
else
download_version="$latest_release"
fi
info "Detected environment: $os_name ($arch)"
info "Targeting release tag: ${download_version}"
info "Targeting version: ${download_version}"
download_prefix="https://github.com/palera1n/palera1n/releases/download"
mkdir -p "$bin_path"
@@ -267,12 +298,17 @@ case "$os" in
tgz_url="${download_prefix}/${download_version}/palera1n-macos-${arch}.tar.gz"
bin_url="${download_prefix}/${download_version}/palera1n-macos-${arch}"
if curl -fsLI "$dmg_url" >/dev/null 2>&1; then
error "DMG releases are not supported by this CLI installer. Please download the DMG manually."
exit 1
fi
hdiutil detach "/Volumes/palera1n-macos-universal" >/dev/null 2>&1 || true
if curl -fsLI "$tgz_url" >/dev/null 2>&1; then
if curl -fsLI "$dmg_url" >/dev/null 2>&1; then
info "Downloading macOS DMG..."
dmg_file="$TMPDIR/palera1n-macos-universal-$(date +%s).dmg"
download "$dmg_url" "$dmg_file"
hdiutil attach "$dmg_file" >/dev/null 2>&1
open "/Volumes/palera1n-macos-universal"
rm -f -- "$dmg_file"
downloaded_dmg="1"
elif curl -fsLI "$tgz_url" >/dev/null 2>&1; then
info "Installing from macOS tarball..."
curl -fsSL "$tgz_url" | tar -xz -C "$prefix_path"
else
@@ -283,6 +319,11 @@ case "$os" in
;;
esac
if [ "$downloaded_dmg" = "1" ]; then
info "palera1n DMG downloaded. Please drag the palera1n app to your Applications folder."
exit 0
fi
add_to_path "$bin_path"
if [ -f "$install_path" ]; then
@@ -294,7 +335,7 @@ if [ -f "$install_path" ]; then
info "palera1n installed successfully at ${install_path}."
info "Type \`palera1n\` in your terminal to get started!"
exec "${SHELL:-/bin/sh}" -l
else
else
error "palera1n failed to install. Please check your internet connection and try again."
exit 1
fi
+3
View File
@@ -369,6 +369,9 @@ static struct irecv_device irecv_devices[] = {
/* Apple Vision Pro */
{ "RealityDevice14,1", "n301ap", 0x42, 0x8112, "Apple Vision Pro" },
{ "RealityDevice17,1", "n301aap", 0x42, 0x8142, "Apple Vision Pro (M5)" },
/* Lightning Video Adapters */
{ "iAccy1,1", "b137ap", 0x00, 0x8747, "Lightning Digital AV Adapter" },
{ "iAccy1,2", "b165ap", 0x02, 0x8747, "Lightning to VGA Adapter" },
/* Private Cloud Compute Research Environment */
{ "iPhone99,11", "vresearch101ap", 0x90, 0xFE01, "iPhone 99,11" },
{ nullptr, nullptr, -1, -1, nullptr }
+9 -1
View File
@@ -73,6 +73,7 @@ struct ManagedDevice {
bool normalPresent = false;
bool recoveryPresent = false;
bool dfuPresent = false;
bool pongoPresent = false;
hotplug_handle_t handle{};
uint32_t device_id = 0;
@@ -279,6 +280,7 @@ static void handle_other_add(hotplug_handle_t handle, DeviceMode mode) {
m.recoveryPresent = (mode == DeviceMode::Recovery);
m.dfuPresent = (mode == DeviceMode::DFU);
m.pongoPresent = (mode == DeviceMode::Pongo);
}
publish_state();
}
@@ -304,6 +306,7 @@ static void remove_device(platform_service_t service, DeviceMode mode, uint32_t
switch (mode) {
case DeviceMode::Recovery: return pair.second.recoveryPresent;
case DeviceMode::DFU: return pair.second.dfuPresent;
case DeviceMode::Pongo: return pair.second.pongoPresent;
default: return false;
}
});
@@ -319,9 +322,11 @@ static void remove_device(platform_service_t service, DeviceMode mode, uint32_t
m.recoveryPresent = false;
} else if (mode == DeviceMode::DFU) {
m.dfuPresent = false;
} else if (mode == DeviceMode::Pongo) {
m.pongoPresent = false;
}
if (!m.normalPresent && !m.recoveryPresent && !m.dfuPresent) {
if (!m.normalPresent && !m.recoveryPresent && !m.dfuPresent && !m.pongoPresent) {
release_handle(m.handle);
g_devices.erase(it);
}
@@ -419,6 +424,9 @@ static void hotplug_callback(hotplug_event_t event, hotplug_handle_t handle) {
case HOTPLUG_EVENT_DFU_REMOVE: remove_device(srv, DeviceMode::DFU); break;
case HOTPLUG_EVENT_RECOVERY_ADD: handle_other_add(handle, DeviceMode::Recovery); break;
case HOTPLUG_EVENT_RECOVERY_REMOVE: remove_device(srv, DeviceMode::Recovery); break;
case HOTPLUG_EVENT_PONGO_ADD: handle_other_add(handle, DeviceMode::Pongo); break;
case HOTPLUG_EVENT_PONGO_REMOVE: remove_device(srv, DeviceMode::Pongo); break;
default: break;
}
}
+2 -1
View File
@@ -43,7 +43,8 @@ enum class DeviceMode
None,
Normal,
Recovery,
DFU
DFU,
Pongo,
};
struct DeviceState
+11 -7
View File
@@ -35,15 +35,16 @@
#include <atomic>
#include <chrono>
constexpr int32_t APPLE_VID = 0x05AC;
constexpr int32_t PID_DFU = 0x1227;
constexpr int32_t PID_RECOVERY_1 = 0x1280;
constexpr int32_t PID_RECOVERY_2 = 0x1281;
constexpr int32_t PID_RECOVERY_3 = 0x1282;
constexpr int32_t PID_RECOVERY_4 = 0x1283;
constexpr int32_t APPLE_VID = 0x05AC;
constexpr int32_t PID_DFU = 0x1227;
constexpr int32_t PID_RECOVERY_1 = 0x1280;
constexpr int32_t PID_RECOVERY_2 = 0x1281;
constexpr int32_t PID_RECOVERY_3 = 0x1282;
constexpr int32_t PID_RECOVERY_4 = 0x1283;
constexpr int32_t PID_PONGO = 0x4141;
static const std::vector<int32_t> TARGET_PIDS = {
PID_DFU, PID_RECOVERY_1, PID_RECOVERY_2, PID_RECOVERY_3, PID_RECOVERY_4
PID_DFU, PID_RECOVERY_1, PID_RECOVERY_2, PID_RECOVERY_3, PID_RECOVERY_4, PID_PONGO
};
static hotplug_callback_t gUserCallback = nullptr;
@@ -56,6 +57,9 @@ static hotplug_event_t get_hotplug_event(int32_t pid, bool arrived) {
if (pid == PID_DFU) {
return arrived ? HOTPLUG_EVENT_DFU_ADD : HOTPLUG_EVENT_DFU_REMOVE;
}
if (pid == PID_PONGO) {
return arrived ? HOTPLUG_EVENT_PONGO_ADD : HOTPLUG_EVENT_PONGO_REMOVE;
}
return arrived ? HOTPLUG_EVENT_RECOVERY_ADD : HOTPLUG_EVENT_RECOVERY_REMOVE;
}
+3 -1
View File
@@ -51,7 +51,9 @@ typedef enum {
HOTPLUG_EVENT_DFU_ADD,
HOTPLUG_EVENT_DFU_REMOVE,
HOTPLUG_EVENT_RECOVERY_ADD,
HOTPLUG_EVENT_RECOVERY_REMOVE
HOTPLUG_EVENT_RECOVERY_REMOVE,
HOTPLUG_EVENT_PONGO_ADD,
HOTPLUG_EVENT_PONGO_REMOVE,
} hotplug_event_t;
typedef struct {
+2
View File
@@ -67,6 +67,7 @@ const char* stage_to_string(int stage)
case STAGE_YOLODFU: return "Booting PongoOS...";
case STAGE_PONGO: return "Booting...";
case STAGE_DONE: return "Done!";
case STAGE_ERROR: return "Error!";
default: return "Waiting...";
}
}
@@ -80,6 +81,7 @@ int stage_to_progress(int stage)
case STAGE_YOLODFU: return 60;
case STAGE_PONGO: return 70;
case STAGE_DONE: return 100;
case STAGE_ERROR: return 99;
default: return 0;
}
}
+26 -3
View File
@@ -39,7 +39,7 @@
#endif
#if WITH_RAMDISK
# include "gen/embedded/ramdisk.h"
# include "gen/embedded/ramdisk-compressed.dmg.h"
# include "gen/embedded/ramdisk-compressed.h"
#endif
#include "gen/embedded/Pongo.h"
#include "gen/embedded/checkra1n-kpf-pongo.h"
@@ -64,8 +64,8 @@ payload_t g_payload_overlay = {
#if WITH_RAMDISK
payload_t g_payload_ramdisk = {
.data = embedded_ramdisk_compressed_dmg_lzma,
.data_len = embedded_ramdisk_compressed_dmg_lzma_len,
.data = embedded_ramdisk_compressed_lzma,
.data_len = embedded_ramdisk_compressed_lzma_len,
.uncompressed_data_len = embedded_ramdisk_dmg_len,
};
#else
@@ -88,6 +88,29 @@ payload_t g_payload_kpf = {
.uncompressed_data_len = embedded_checkra1n_kpf_pongo_len,
};
#define PONGO_MAX_SZ (0x7fe00)
#define MACHO_MAGIC_32 (0xFEEDFACE)
#define MACHO_MAGIC_64 (0xFEEDFACF)
bool check_payload_validity(const payload_t *payload, bool isPongo)
{
if (!payload || !payload->data || payload->data_len < 4)
return false;
const uint32_t magic = *(const uint32_t *)payload->data;
const bool isMachO = (magic == MACHO_MAGIC_32 || magic == MACHO_MAGIC_64);
if (isPongo) {
if (isMachO || payload->data_len > PONGO_MAX_SZ)
return false;
} else {
if (!isMachO)
return false;
}
return true;
}
bool override_payload_from_file(const char *path, payload_t *out)
{
FILE *f = fopen(path, "rb");
+1
View File
@@ -52,6 +52,7 @@ extern payload_t g_payload_kpf;
extern "C" {
#endif
bool check_payload_validity(const payload_t *payload, bool isPongo);
bool override_payload_from_file(const char *path, payload_t *out);
#ifdef __cplusplus
+114 -123
View File
@@ -65,7 +65,7 @@ void print_credits() {
"::\n"
":: ======== Made by =======>\n"
":: Made by: asdfugil, kok3shidoll, claration, mineek\n"
":: plooshi, staturnz\n"
":: sarah, staturnz\n"
":: ======== Thanks to =======>\n"
":: Thanks to: itsnebulalol, llsc12, lrdsnow, dedbeddedbed\n"
":: kirb, ehilwyma, opa334, 0x7ff, alfiecg25, sneko, sbingner\n"
@@ -103,6 +103,7 @@ void print_usage(char* argv) {
" -T, --telnetd Enable TELNET daemon on port 46 (insecure)\n"
" -V, --verbose-boot Enable verbose booting\n"
" -p, --early-exit Exit after uploading Pongo\n"
" -P, --late-exit Exit after uploading existing images to Pongo\n"
" -e, --extra-bootargs <BOOTARGS> Set extra bootargs\n"
" -k, --override-pongo <FILE PATH> Override Pongo image\n"
" -K, --override-kpf <FILE PATH> Override kernel patchfinder\n"
@@ -136,6 +137,7 @@ void print_usage(char* argv) {
" RA1N_TELNETD=1 Enable TELNET daemon on port 46 (insecure)\n"
" RA1N_VERBOSE_BOOT=1 Enable verbose booting\n"
" RA1N_EARLY_EXIT=1 Exit after uploading Pongo\n"
" RA1N_LATE_EXIT=1 Exit after uploading existing images to Pongo\n"
" RA1N_EXTRA_BOOTARGS=<FILE PATH> Set extra bootargs\n"
" RA1N_OVERRIDE_PONGO=<FILE PATH> Override Pongo image\n"
" RA1N_OVERRIDE_KPF=<FILE PATH> Override kernel patchfinder\n"
@@ -171,15 +173,6 @@ void parse_arguments(int argc, char* argv[]) {
int options;
int option_index = 0;
bool set_cli = false, set_gui = false, set_tui = false;
bool set_flower = false, set_force_revert = false, set_ssv = false;
bool set_rootless = false, set_rootful = false;
bool set_fakefs = false, set_partial_fakefs = false;
bool set_safemode = false, set_telnetd = false, set_verbose = false;
bool set_pongo_exit = false, set_no_colors = false, set_quick = false;
bool set_extra_bootargs = false, set_pongo = false, set_kpf = false;
bool set_overlay = false, set_ramdisk = false;
static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
@@ -202,6 +195,7 @@ void parse_arguments(int argc, char* argv[]) {
{"telnetd", no_argument, NULL, 'T'},
{"verbose-boot", no_argument, NULL, 'V'},
{"early-exit", no_argument, NULL, 'p'},
{"late-exit", no_argument, NULL, 'P'},
{"extra-bootargs", required_argument, NULL, 'e'},
{"override-pongo", required_argument, NULL, 'k'},
{"override-kpf", required_argument, NULL, 'K'},
@@ -241,7 +235,7 @@ void parse_arguments(int argc, char* argv[]) {
// MARK: Standard
while ((options = getopt_long(argc, argv, "hvlfcBsTVpe:k:K:o:r:dnq", long_options, &option_index)) != -1) {
while ((options = getopt_long(argc, argv, "hvlfcBsTVpPe:k:K:o:r:dnq", long_options, &option_index)) != -1) {
switch (options) {
case 'h': // --help
print_usage(argv[0]);
@@ -294,11 +288,9 @@ void parse_arguments(int argc, char* argv[]) {
palerain_flags |= palerain_option_ssv;
break;
case 'l': // --rootless
palerain_flags &= ~palerain_option_rootful;
palerain_flags |= palerain_option_rootless;
break;
case 'f': // --rootful
palerain_flags &= ~palerain_option_rootless;
palerain_flags |= palerain_option_rootful;
break;
case 'c': // --setup-fakefs
@@ -319,6 +311,9 @@ void parse_arguments(int argc, char* argv[]) {
case 'p': // --early-exit
palerain_flags |= palerain_option_pongo_exit;
break;
case 'P': // --late-exit
palerain_flags |= palerain_option_pongo_full;
break;
case 'e': // --extra-bootargs
if (strlen(optarg) > (sizeof(boot_args) - 0x20)) {
LOG_ERROR("Boot arguments too long!");
@@ -338,11 +333,10 @@ void parse_arguments(int argc, char* argv[]) {
LOG_ERROR("Failed to load pongo payload, is the path correct?");
exit(1);
}
if (g_payload_pongo.data_len > PONGO_MAX_SZ) {
LOG_ERROR("Pongo payload is too large! %zu bytes (max %zu)", g_payload_pongo.data_len, PONGO_MAX_SZ);
if (!check_payload_validity(&g_payload_pongo, true)) {
LOG_ERROR("Pongo payload is invalid or too large! %zu bytes", g_payload_pongo.data_len);
exit(1);
}
// TODO: check if macho, otherwise exit
LOG("Overriding pongo payload with %s", optarg);
break;
case 'K': // --override-kpf
@@ -350,11 +344,8 @@ void parse_arguments(int argc, char* argv[]) {
LOG_ERROR("Failed to load kpf payload, is the path correct?");
exit(1);
}
if (g_payload_kpf.data_len < 4
|| (memcmp(g_payload_kpf.data, MACHO_MAGIC_64, 4) != 0
&& memcmp(g_payload_kpf.data, MACHO_MAGIC_32, 4) != 0))
{
LOG_ERROR("Invalid kpf payload, is it macho?");
if (!check_payload_validity(&g_payload_kpf, false)) {
LOG_ERROR("KPF payload is invalid! Is it a valid Mach-O binary?");
exit(1);
}
LOG("Overriding kpf payload with %s", optarg);
@@ -394,65 +385,66 @@ void parse_arguments(int argc, char* argv[]) {
// MARK: Environment vars
if (!set_cli && get_env_binary("RA1N_CLI") == 1) {
if (get_env_binary("RA1N_CLI") == 1) {
palerain_flags &= ~palerain_option_tui;
palerain_flags &= ~palerain_option_gui;
palerain_flags |= palerain_option_cli;
}
#ifdef WITH_GUI
if (!set_gui && get_env_binary("RA1N_GUI") == 1) {
if (get_env_binary("RA1N_GUI") == 1) {
palerain_flags &= ~palerain_option_cli;
palerain_flags &= ~palerain_option_tui;
palerain_flags |= palerain_option_gui;
}
#endif
#ifdef WITH_TUI
if (!set_tui && get_env_binary("RA1N_TUI") == 1) {
if (get_env_binary("RA1N_TUI") == 1) {
palerain_flags &= ~palerain_option_cli;
palerain_flags &= ~palerain_option_gui;
palerain_flags |= palerain_option_tui;
}
#endif
if (!set_flower && get_env_binary("RA1N_DARK_BLOCKCHAIN") == 1) {
if (get_env_binary("RA1N_DARK_BLOCKCHAIN") == 1) {
palerain_flags |= palerain_option_flower_chain;
}
if (!set_force_revert && get_env_binary("RA1N_FORCE_REVERT") == 1) {
if (get_env_binary("RA1N_FORCE_REVERT") == 1) {
palerain_flags |= palerain_option_force_revert;
}
if (!set_ssv && get_env_binary("RA1N_FORCE_ENABLE_SSV") == 1) {
if (get_env_binary("RA1N_FORCE_ENABLE_SSV") == 1) {
palerain_flags |= palerain_option_ssv;
}
if (!set_rootless && get_env_binary("RA1N_ROOTLESS") == 1) {
palerain_flags &= ~palerain_option_rootful;
if (get_env_binary("RA1N_ROOTLESS") == 1) {
palerain_flags |= palerain_option_rootless;
}
if (!set_rootful && get_env_binary("RA1N_ROOTFUL") == 1) {
palerain_flags &= ~palerain_option_rootless;
if (get_env_binary("RA1N_ROOTFUL") == 1) {
palerain_flags |= palerain_option_rootful;
}
if (!set_fakefs && get_env_binary("RA1N_SETUP_FAKEFS") == 1) {
if (get_env_binary("RA1N_SETUP_FAKEFS") == 1) {
palerain_flags |= palerain_option_setup_rootful;
}
if (!set_partial_fakefs && get_env_binary("RA1N_SETUP_PARTIAL_FAKEFS") == 1) {
if (get_env_binary("RA1N_SETUP_PARTIAL_FAKEFS") == 1) {
palerain_flags |= palerain_option_setup_partial_root;
}
if (!set_safemode && get_env_binary("RA1N_SAFE_MODE") == 1) {
if (get_env_binary("RA1N_SAFE_MODE") == 1) {
palerain_flags |= palerain_option_safemode;
}
if (!set_telnetd && get_env_binary("RA1N_TELNETD") == 1) {
if (get_env_binary("RA1N_TELNETD") == 1) {
palerain_flags |= palerain_option_telnetd;
}
if (!set_verbose && get_env_binary("RA1N_VERBOSE_BOOT") == 1) {
if (get_env_binary("RA1N_VERBOSE_BOOT") == 1) {
palerain_flags |= palerain_option_verbose_boot;
}
if (!set_pongo_exit && get_env_binary("RA1N_EARLY_EXIT") == 1) {
if (get_env_binary("RA1N_EARLY_EXIT") == 1) {
palerain_flags |= palerain_option_pongo_exit;
}
if (!set_no_colors && get_env_binary("RA1N_NO_COLORS") == 1) {
if (get_env_binary("RA1N_LATE_EXIT") == 1) {
palerain_flags |= palerain_option_pongo_full;
}
if (get_env_binary("RA1N_NO_COLORS") == 1) {
palerain_flags |= palerain_option_no_colors;
}
#if defined(WITH_GUI) || defined(WITH_TUI)
if (!set_quick && get_env_binary("RA1N_QUICK") == 1) {
if (get_env_binary("RA1N_QUICK") == 1) {
palerain_flags |= palerain_option_quick;
}
#endif
@@ -465,116 +457,115 @@ void parse_arguments(int argc, char* argv[]) {
}
}
if (!set_extra_bootargs) {
const char *env_bootargs = getenv("RA1N_EXTRA_BOOTARGS");
if (env_bootargs) {
if (strlen(env_bootargs) > (sizeof(boot_args) - 0x20)) {
LOG_ERROR("Boot arguments too long!");
exit(1);
}
snprintf(boot_args, sizeof(boot_args), "%s", env_bootargs);
const char *env_bootargs = getenv("RA1N_EXTRA_BOOTARGS");
if (env_bootargs) {
if (strlen(env_bootargs) > (sizeof(boot_args) - 0x20)) {
LOG_ERROR("Boot arguments too long!");
exit(1);
}
snprintf(boot_args, sizeof(boot_args), "%s", env_bootargs);
}
if (!set_pongo) {
const char *env_pongo = getenv("RA1N_OVERRIDE_PONGO");
if (env_pongo) {
if (!override_payload_from_file(env_pongo, &g_payload_pongo)) {
LOG_ERROR("Failed to load pongo payload from env, is the path correct?");
exit(1);
}
if (g_payload_pongo.data_len > PONGO_MAX_SZ) {
LOG_ERROR("Pongo payload is too large! %zu bytes (max %zu)", g_payload_pongo.data_len, PONGO_MAX_SZ);
exit(1);
}
LOG("Overriding pongo payload with %s (from env)", env_pongo);
const char *env_pongo = getenv("RA1N_OVERRIDE_PONGO");
if (env_pongo) {
if (!override_payload_from_file(env_pongo, &g_payload_pongo)) {
LOG_ERROR("Failed to load pongo payload from env, is the path correct?");
exit(1);
}
if (!check_payload_validity(&g_payload_pongo, true)) {
LOG_ERROR("Pongo payload is invalid or too large! %zu bytes", g_payload_pongo.data_len);
exit(1);
}
LOG("Overriding pongo payload with %s (from env)", env_pongo);
}
if (!set_kpf) {
const char *env_kpf = getenv("RA1N_OVERRIDE_KPF");
if (env_kpf) {
if (!override_payload_from_file(env_kpf, &g_payload_kpf)) {
LOG_ERROR("Failed to load kpf payload from env, is the path correct?");
exit(1);
}
if (g_payload_kpf.data_len < 4
|| (memcmp(g_payload_kpf.data, MACHO_MAGIC_64, 4) != 0
&& memcmp(g_payload_kpf.data, MACHO_MAGIC_32, 4) != 0))
{
LOG_ERROR("Invalid kpf payload from env, is it macho?");
exit(1);
}
LOG("Overriding kpf payload with %s (from env)", env_kpf);
const char *env_kpf = getenv("RA1N_OVERRIDE_KPF");
if (env_kpf) {
if (!override_payload_from_file(env_kpf, &g_payload_kpf)) {
LOG_ERROR("Failed to load kpf payload from env, is the path correct?");
exit(1);
}
if (!check_payload_validity(&g_payload_kpf, false)) {
LOG_ERROR("Invalid kpf payload from env, is it macho?");
exit(1);
}
LOG("Overriding kpf payload with %s (from env)", env_kpf);
}
if (!set_overlay) {
const char *env_overlay = getenv("RA1N_OVERRIDE_OVERLAY");
if (env_overlay) {
if (!override_payload_from_file(env_overlay, &g_payload_overlay)) {
LOG_ERROR("Failed to load overlay payload from env, is the path correct?");
exit(1);
}
LOG("Overriding overlay payload with %s (from env)", env_overlay);
const char *env_overlay = getenv("RA1N_OVERRIDE_OVERLAY");
if (env_overlay) {
if (!override_payload_from_file(env_overlay, &g_payload_overlay)) {
LOG_ERROR("Failed to load overlay payload from env, is the path correct?");
exit(1);
}
LOG("Overriding overlay payload with %s (from env)", env_overlay);
}
if (!set_ramdisk) {
const char *env_ramdisk = getenv("RA1N_OVERRIDE_RAMDISK");
if (env_ramdisk) {
if (!override_payload_from_file(env_ramdisk, &g_payload_ramdisk)) {
LOG_ERROR("Failed to load ramdisk payload from env, is the path correct?");
exit(1);
}
LOG("Overriding ramdisk payload with %s (from env)", env_ramdisk);
const char *env_ramdisk = getenv("RA1N_OVERRIDE_RAMDISK");
if (env_ramdisk) {
if (!override_payload_from_file(env_ramdisk, &g_payload_ramdisk)) {
LOG_ERROR("Failed to load ramdisk payload from env, is the path correct?");
exit(1);
}
LOG("Overriding ramdisk payload with %s (from env)", env_ramdisk);
}
// MARK: Flag checks
if (!(palerain_flags & palerain_option_gui) &&
!(palerain_flags & palerain_option_tui))
if ((palerain_flags & palerain_option_pongo_exit) &&
(palerain_flags & palerain_option_pongo_full))
{
if ((palerain_flags & palerain_option_pongo_exit) &&
((palerain_flags & palerain_option_rootful) ||
(palerain_flags & palerain_option_rootless) ||
(palerain_flags & palerain_option_setup_rootful) ||
(palerain_flags & palerain_option_setup_partial_root)))
LOG_ERROR("You cannot specify both early-exit and late-exit modes.\n");
print_usage(argv[0]);
exit(1);
}
// Pongo exit modes are standalone and cannot be combined with root modes
if (palerain_flags & (palerain_option_pongo_exit | palerain_option_pongo_full))
{
if (palerain_flags & (palerain_option_rootful | palerain_option_rootless))
{
LOG_ERROR("[-p, --early-exit] cannot be used with [-f, --rootful], [-l, --rootless], [-c, --setup-fakefs], or [-B, --setup-partial-fakefs].\n");
LOG_ERROR("Pongo exit modes cannot be used with [-l, --rootless] or [-f, --rootful].\n");
print_usage(argv[0]);
exit(1);
}
if (!(palerain_flags & palerain_option_pongo_exit) &&
!(palerain_flags & palerain_option_rootful) &&
!(palerain_flags & palerain_option_rootless))
{
LOG_ERROR("You must specify either [-l, --rootless] or [-f, --rootful].\n");
print_usage(argv[0]);
exit(1);
}
goto skip_root_types;
}
if ((palerain_flags & palerain_option_rootful) &&
(palerain_flags & palerain_option_rootless))
{
LOG_ERROR("You cannot specify both [-l, --rootless] and [-f, --rootful].\n");
print_usage(argv[0]);
exit(1);
}
// Normal root checks
if (!(palerain_flags & palerain_option_gui) &&
!(palerain_flags & palerain_option_tui) &&
!(palerain_flags & palerain_option_rootful) &&
!(palerain_flags & palerain_option_rootless))
{
LOG_ERROR("You must specify either [-l, --rootless] or [-f, --rootful].\n");
print_usage(argv[0]);
exit(1);
}
if ((palerain_flags & palerain_option_setup_rootful) &&
(palerain_flags & palerain_option_setup_partial_root))
{
LOG_ERROR("You cannot specify both [-c, --setup-fakefs] and [-B, --setup-partial-fakefs].\n");
print_usage(argv[0]);
exit(1);
}
if ((palerain_flags & palerain_option_rootful) &&
(palerain_flags & palerain_option_rootless))
{
LOG_ERROR("You cannot specify both [-l, --rootless] and [-f, --rootful].\n");
print_usage(argv[0]);
exit(1);
}
if (((palerain_flags & palerain_option_setup_rootful) ||
(palerain_flags & palerain_option_setup_partial_root)) &&
!(palerain_flags & palerain_option_rootful))
skip_root_types:
if ((palerain_flags & palerain_option_setup_rootful) &&
(palerain_flags & palerain_option_setup_partial_root))
{
LOG_ERROR("You cannot specify both [-c, --setup-fakefs] and [-B, --setup-partial-fakefs].\n");
print_usage(argv[0]);
exit(1);
}
if ((palerain_flags & palerain_option_setup_rootful) ||
(palerain_flags & palerain_option_setup_partial_root))
{
if (!(palerain_flags & palerain_option_rootful))
{
LOG_ERROR("[-c, --setup-fakefs] or [-B, --setup-partial-fakefs] require [-f, --rootful].\n");
print_usage(argv[0]);
+23 -18
View File
@@ -62,9 +62,7 @@ p1_transfer_ret_t issue_pongo_command(const p1_usb_handle_t *handle, const char
if (command != NULL) {
size_t len = strlen(command);
// unlikely to happen, unless we add support for pongoterm
// TODO: discuss on adding a pongoterm
if (len > CMD_LENGTH_MAX) {
if (len >= CMD_LENGTH_MAX) {
LOG_ERROR("Pongo command too long: %s", command);
result.ret = 1;
return result;
@@ -86,12 +84,8 @@ p1_transfer_ret_t issue_pongo_command(const p1_usb_handle_t *handle, const char
result = send_interface_control_request(handle, 0x21, 3, 0, 0, command_buf, len);
if (result.ret != USB_TRANSFER_OK) goto result;
#endif
// return early if the command is boot, we dont care about results
if (strncmp(command,"boot",4) == 0) goto result;
}
// TODO: does this work correctly?
while (in_progress) {
#if WITH_CIDERRAIN
result = usb_ctrl_transfer(handle, 0xA1, 2, 0, 0, &in_progress, sizeof(in_progress));
@@ -101,26 +95,35 @@ p1_transfer_ret_t issue_pongo_command(const p1_usb_handle_t *handle, const char
if (result.ret != USB_TRANSFER_OK) goto result;
#endif
if (in_progress == 0) break;
if (outpos + 0x1000 >= sizeof(stdout_buf)) {
memmove(stdout_buf, stdout_buf + 0x1000, sizeof(stdout_buf) - 0x1000);
outpos -= 0x1000;
if (!in_progress) break;
if (outpos > 0x1000) {
memmove(stdout_buf, stdout_buf + outpos - 0x1000, 0x1000);
outpos = 0x1000;
}
outlen = 0;
#if WITH_CIDERRAIN
result = usb_ctrl_transfer(handle, 0xA1, 1, 0, 0, stdout_buf + outpos, 0x1000);
result = usb_ctrl_transfer(handle, 0xA1, 1, 0, 0, (uint8_t *)(stdout_buf + outpos), 0x1000);
if (result.ret != kUSBResponseSuccess) goto result;
outlen = result.wLenDone;
#else
result = send_interface_control_request(handle, 0xA1, 1, 0, 0, stdout_buf + outpos, 0x1000);
if (result.ret != USB_TRANSFER_OK) goto result;
outlen = result.sz;
#endif
outlen = 0x1000;
outpos += outlen;
}
result:
result:
if (result.ret != 0) {
// boot command, we don't care about results, lets assume success :-)
if (command != NULL && (!strncmp("boot", command, 4))) {
result.ret = 0;
return result;
}
LOG_ERROR("PongoOS command output: %.*s", (int)outpos, stdout_buf);
}
return result;
}
@@ -199,8 +202,6 @@ p1_checkm8_err_t send_compressed_pongo(p1_usb_handle_t *handle, const uint8_t *p
return cr;
}
// TODO: support early-exit but with all embedded artifacts already loaded
p1_checkm8_err_t send_full_pongo_jailbreak(p1_usb_handle_t *handle)
{
p1_transfer_ret_t result;
@@ -280,10 +281,14 @@ p1_checkm8_err_t send_full_pongo_jailbreak(p1_usb_handle_t *handle)
if (result.ret != 0) goto bad;
}
if (palerain_flags & palerain_option_pongo_full)
goto good;
// TODO: why do we check results
result = issue_pongo_command(handle, "bootx");
if (result.ret != 0) goto bad;
good:
return 0;
bad:
return 255;
-5
View File
@@ -46,11 +46,6 @@ typedef transfer_ret_t p1_transfer_ret_t;
typedef checkm8_err_t p1_checkm8_err_t;
#endif
#define PONGO_MAX_SZ (0x7fe00)
// used for checking overridden files (KPF mainly)
#define MACHO_MAGIC_32 (const unsigned char[]){ 0xCE, 0xFA, 0xED, 0xFE }
#define MACHO_MAGIC_64 (const unsigned char[]){ 0xCF, 0xFA, 0xED, 0xFE }
p1_checkm8_err_t send_compressed_pongo(p1_usb_handle_t *handle, const uint8_t *pongo_bin, const size_t pongo_bin_length);
p1_checkm8_err_t send_full_pongo_jailbreak(p1_usb_handle_t *handle);
+4 -4
View File
@@ -28,7 +28,7 @@
#if defined(WITH_GUI) || defined(WITH_TUI)
#include <nlohmann/json.hpp>
#include "gen/embedded/DFUHelperDeviceInfo.h"
#include "gen/embedded/DFUHelperDeviceInfo-minified.h"
#include "sequence.hpp"
DfuSequence ParseSequence(const std::string& deviceKey)
@@ -36,9 +36,9 @@ DfuSequence ParseSequence(const std::string& deviceKey)
DfuSequence seq;
static nlohmann::json j = nlohmann::json::parse(
embedded_DFUHelperDeviceInfo_json,
embedded_DFUHelperDeviceInfo_json +
embedded_DFUHelperDeviceInfo_json_len
embedded_DFUHelperDeviceInfo_minified_json,
embedded_DFUHelperDeviceInfo_minified_json +
embedded_DFUHelperDeviceInfo_minified_json_len
);
auto itMap = j["devicemap"].find(deviceKey);
-6
View File
@@ -118,12 +118,6 @@ void TuiExploitPanel::exploit()
std::thread([this]()
{
const DeviceState deviceState = GetFrame()->GetDeviceState();
if (!deviceState.connected || deviceState.mode != DeviceMode::DFU) {
m_is_exploiting = false;
return;
}
auto stage = std::make_shared<std::atomic<int>>(STAGE_RESET);
auto result = std::make_shared<std::atomic<int>>(0);
+32 -10
View File
@@ -53,9 +53,6 @@ static std::string get_device_title(const DeviceState& state) {
}
const std::string product = state.displayName.empty() ? (state.productType.empty() ? "Unknown" : state.productType) : state.displayName;
if (state.mode == DeviceMode::DFU) {
return "DFU Mode device";
}
return product;
}
@@ -74,7 +71,7 @@ static std::string get_device_subtitle(const DeviceState& state) {
switch (state.mode) {
case DeviceMode::Normal:
if (state.requiresCLI) {
return "Sorry, jailbreaking is only available via CLI mode * iOS " + version + "\n" + ecid;
return "Sorry, jailbreaking is only available via DFU mode * iOS " + version + "\n" + ecid;
} else if (state.isSupported) {
return "Connected in normal mode * iOS " + version + "\n" + ecid;
} else {
@@ -82,14 +79,24 @@ static std::string get_device_subtitle(const DeviceState& state) {
}
case DeviceMode::Recovery:
if (state.requiresCLI) {
return "Sorry, jailbreaking is only available via CLI mode.\n" + ecid;
return "Sorry, jailbreaking is only available via DFU mode.\n" + ecid;
} else if (state.isSupported) {
return "Connected in recovery mode.\n" + ecid;
} else {
return "Sorry, this recovery device is not supported.\n" + ecid;
}
case DeviceMode::DFU:
return "Sorry, jailbreaking in DFU is not supported.\n";
if (state.isSupported) {
return "Connected in DFU mode.\n" + ecid;
} else {
return "Sorry, this DFU device is not supported.\n" + ecid;
}
case DeviceMode::Pongo:
if (state.isSupported) {
return "Connected in PongoOS mode.\n" + ecid;
} else {
return "This PongoOS device is not supported, worth a shot though...\n" + ecid;
}
case DeviceMode::None:
return "Please connect a device to get started. Ensure version range is 15.0+";
}
@@ -136,7 +143,7 @@ void TuiMainPanel::draw(int sy, int sx, int selected) {
}
const std::string made_by =
"Made by: asdfugil, claration, kok3shidoll, mineek, plooshi, staturnz";
"Made by: asdfugil, claration, kok3shidoll, mineek, sarah, staturnz";
const std::string thanks_to =
"Thanks to: itsnebulalol, llsc12, lrdsnow, dedbeddedbed, kirb, ehilwyma, "
"opa334, 0x7ff, alfiecg24, sneko, sbingner, nikias, "
@@ -223,14 +230,23 @@ void TuiMainPanel::handle_enter(int selected, int sy, int sx) {
case 1:
GetFrame()->ShowSettings(5);
break;
case 2: {
if (block_start) break;
bool can_start = (state.connected && state.isSupported && !state.requiresCLI && state.mode != DeviceMode::DFU);
bool isDfuLike =
state.mode == DeviceMode::DFU ||
state.mode == DeviceMode::Pongo;
bool can_start =
state.connected &&
state.isSupported &&
(isDfuLike || !state.requiresCLI);
if (can_start) {
if (state.mode == DeviceMode::Recovery) {
GetFrame()->ShowDfu(1);
} else if (isDfuLike) {
GetFrame()->ShowExploit(0);
} else {
GetFrame()->ShowRecovery(1);
}
@@ -261,7 +277,13 @@ bool TuiMainPanel::is_button_enabled(int btn_idx) const {
switch(btn_idx) {
case 0: return true;
case 1: return true;
case 2: return (state.connected && state.isSupported && !state.requiresCLI && state.mode != DeviceMode::DFU);
case 2: {
bool isDfuLike =
state.mode == DeviceMode::DFU ||
state.mode == DeviceMode::Pongo;
return state.connected && state.isSupported && (isDfuLike || !state.requiresCLI);
}
case 3: return true;
}
+26 -18
View File
@@ -69,14 +69,16 @@ void TuiSettingsPanel::draw(int sy, int sx, int selected) {
!!(palerain_flags & palerain_option_safemode),
!!(palerain_flags & palerain_option_verbose_boot),
!!(palerain_flags & palerain_option_force_revert),
!!(palerain_flags & palerain_option_flower_chain)
!!(palerain_flags & palerain_option_flower_chain),
!!(palerain_flags & palerain_option_ssv)
};
const char *labels[] = {
"Safe Mode",
"Verbose Boot",
"Restore System",
"Dark Blockchain"
"Dark Blockchain",
"Force Enable SSV Flag"
};
for (int i = 0; i < 2; i++) {
@@ -98,20 +100,25 @@ void TuiSettingsPanel::draw(int sy, int sx, int selected) {
if (selected == i + 1) attroff(A_REVERSE);
}
mvprintw(sy + 13, content_x, "Jailbreak Type:");
mvprintw(sy + 13, content_x, "[%c] ", states[4] ? 'x' : ' ');
if (selected == 5) attron(A_REVERSE);
mvprintw(sy + 14, content_x + 2, "(%c) Rootless", is_rootful ? ' ' : 'x');
printw("%s", labels[4]);
if (selected == 5) attroff(A_REVERSE);
mvprintw(sy + 15, content_x, "Jailbreak Type:");
if (selected == 6) attron(A_REVERSE);
mvprintw(sy + 15, content_x + 2, "(%c) Rootful", is_rootful ? 'x' : ' ');
mvprintw(sy + 16, content_x + 2, "(%c) Rootless", is_rootful ? ' ' : 'x');
if (selected == 6) attroff(A_REVERSE);
mvprintw(sy + 17, content_x, "Rootful Options:");
if (selected == 7) attron(A_REVERSE);
mvprintw(sy + 17, content_x + 2, "(%c) Rootful", is_rootful ? 'x' : ' ');
if (selected == 7) attroff(A_REVERSE);
mvprintw(sy + 19, content_x, "Rootful Options:");
for (int i = 0; i < 3; ++i) {
const int item_idx = 7 + i;
const int row = sy + 18 + i;
const int item_idx = 8 + i;
const int row = sy + 20 + i;
const bool active = is_rootful;
const bool is_selected = selected == item_idx;
const bool checked = setup_selection == i;
@@ -171,34 +178,35 @@ void TuiSettingsPanel::handle_enter(int selected, int sy, int sx) {
case 2: edit_boot_args(sy, sx); break;
case 3: palerain_flags ^= palerain_option_force_revert; break;
case 4: palerain_flags ^= palerain_option_flower_chain; break;
case 5:
case 5: palerain_flags ^= palerain_option_ssv; break;
case 6:
palerain_flags &= ~(palerain_option_rootless | palerain_option_rootful);
palerain_flags &= ~(palerain_option_setup_rootful | palerain_option_setup_partial_root);
palerain_flags |= palerain_option_rootless;
break;
case 6:
case 7:
palerain_flags &= ~(palerain_option_rootless | palerain_option_rootful);
palerain_flags &= ~(palerain_option_setup_rootful | palerain_option_setup_partial_root);
palerain_flags |= palerain_option_rootful;
break;
case 7:
if (palerain_flags & palerain_option_rootful) {
palerain_flags &= ~(palerain_option_setup_rootful | palerain_option_setup_partial_root);
}
break;
case 8:
if (palerain_flags & palerain_option_rootful) {
palerain_flags &= ~(palerain_option_setup_rootful | palerain_option_setup_partial_root);
palerain_flags |= palerain_option_setup_rootful;
}
break;
case 9:
if (palerain_flags & palerain_option_rootful) {
palerain_flags &= ~(palerain_option_setup_rootful | palerain_option_setup_partial_root);
palerain_flags |= palerain_option_setup_rootful;
}
break;
case 10:
if (palerain_flags & palerain_option_rootful) {
palerain_flags &= ~(palerain_option_setup_rootful | palerain_option_setup_partial_root);
palerain_flags |= palerain_option_setup_partial_root;
}
break;
case 10: GetFrame()->ShowMain(0); break;
case 11: GetFrame()->ShowMain(0); break;
}
}
@@ -207,7 +215,7 @@ void TuiSettingsPanel::handle_device_update(const DeviceState& state) {
}
bool TuiSettingsPanel::is_button_enabled(int btn_idx) const {
if (btn_idx >= 7 && btn_idx <= 9) {
if (btn_idx >= 8 && btn_idx <= 10) {
return (palerain_flags & palerain_option_rootful) != 0;
}
+1 -1
View File
@@ -42,7 +42,7 @@ public:
void handle_device_update(const DeviceState& state) override;
bool is_button_enabled(int btn_idx) const override;
int get_total_items() const override { return 11; }
int get_total_items() const override { return 12; }
int get_button_count() const override { return 1; }
const char** get_buttons() const override;
+7
View File
@@ -71,6 +71,13 @@ MainFrame::MainFrame()
SetSizer(root);
// menu bar
#if __APPLE__
auto* menuBar = new wxMenuBar;
SetMenuBar(menuBar);
#endif
// listeners
Bind(EVT_DEVICE_STATE_UPDATE, [this](wxCommandEvent& e)
{
auto* state = static_cast<DeviceState*>(e.GetClientData());
+8 -3
View File
@@ -160,6 +160,7 @@ void DfuPanel::SetDeviceState(const DeviceState& state)
m_index = m_sequence.steps.size();
m_stepRemaining = -1;
m_actionExecutedIndex = -1;
m_waitingForDfuTransition = true;
const wxColour inactive =
wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
@@ -191,8 +192,11 @@ void DfuPanel::SetDeviceState(const DeviceState& state)
GetMainFrame()->ShowMain();
}
if (!m_isEnteringDfu && !state.connected)
if (!state.connected)
{
if (m_isEnteringDfu || m_waitingForDfuTransition)
return;
m_isEnteringDfu = false;
m_backButton->Enable();
m_startButton->Enable();
@@ -202,6 +206,8 @@ void DfuPanel::SetDeviceState(const DeviceState& state)
void DfuPanel::OnShow(wxShowEvent& event)
{
DevicePanel::OnShow(event);
if (event.IsShown())
{
if (palerain_flags & palerain_option_quick) {
@@ -212,8 +218,6 @@ void DfuPanel::OnShow(wxShowEvent& event)
StartSequence(m_sequence);
}
}
DevicePanel::OnShow(event);
}
void DfuPanel::LoadDevice(const std::string& productType)
@@ -362,6 +366,7 @@ void DfuPanel::StartSequence(const DfuSequence& seq)
m_index = 0;
m_stepRemaining = -1;
m_actionExecutedIndex = -1;
m_waitingForDfuTransition = false;
RunStep();
}
+1
View File
@@ -62,6 +62,7 @@ private:
wxTimer m_timer;
wxTimer m_stagnentTimer;
bool m_isEnteringDfu = false;
bool m_waitingForDfuTransition = false;
wxPanel* m_devicePanel = nullptr;
wxStaticBitmap* m_deviceImage = nullptr;
-6
View File
@@ -109,12 +109,6 @@ void ExploitPanel::StartExploit()
std::thread([this]()
{
const auto deviceState = GetDeviceState();
if (!deviceState.connected || deviceState.mode != DeviceMode::DFU) {
wxTheApp->CallAfter([this]() { m_backButton->Enable(); });
return;
}
auto stage = std::make_shared<std::atomic<int>>(STAGE_RESET);
auto result = std::make_shared<std::atomic<int>>(0);
+32 -7
View File
@@ -74,7 +74,7 @@ MainPanel::MainPanel(MainFrame* frame, wxWindow* parent)
auto* credtext = new wxStaticText(
this,
wxID_ANY,
"Made by: asdfugil, claration, kok3shidoll, mineek, plooshi, staturnz\n\n"
"Made by: asdfugil, claration, kok3shidoll, mineek, sarah, staturnz\n\n"
"Thanks to: itsnebulalol, llsc12, lrdsnow, dedbeddedbed, kirb, ehilwyma, "
"opa334, 0x7ff, alfiecg24, sneko, sbingner, nikias, tihmstar, "
"Checkra1n (Siguza, axi0mx, littlelailo et al.), Procursus (Hayden Seay, "
@@ -133,6 +133,11 @@ MainPanel::MainPanel(MainFrame* frame, wxWindow* parent)
palerain_flags &= ~palerain_option_quick;
});
donateButton->Bind(wxEVT_BUTTON, [](wxCommandEvent&)
{
wxLaunchDefaultBrowser("https://patreon.com/palera1n");
});
optionsButton->Bind(wxEVT_BUTTON, [frame](wxCommandEvent&)
{
frame->ShowSettings();
@@ -144,6 +149,9 @@ MainPanel::MainPanel(MainFrame* frame, wxWindow* parent)
frame->ShowRecovery();
else if (frame->GetDeviceState().mode == DeviceMode::Recovery)
frame->ShowDfu();
else if (frame->GetDeviceState().mode == DeviceMode::DFU ||
frame->GetDeviceState().mode == DeviceMode::Pongo)
frame->ShowExploit();
});
left->Add(m_deviceTitle, 0, wxLEFT | wxRIGHT | wxTOP, 10);
@@ -216,7 +224,7 @@ void MainPanel::SetDeviceState(const DeviceState& state)
m_deviceTitle->SetLabel("Multiple devices detected");
m_deviceSubtitle->SetLabel(
wxString::Format(
"%u USB devices connected. Disconnect extras and keep only one device attached.\n",
"%u USB devices connected. Disconnect extras and keep\nonly one device attached.",
state.connectedDeviceCount
)
);
@@ -241,7 +249,7 @@ void MainPanel::SetDeviceState(const DeviceState& state)
case DeviceMode::Normal:
if (state.requiresCLI) {
m_deviceTitle->SetLabel(productString);
m_deviceSubtitle->SetLabel("Sorry, jailbreaking is only available via CLI mode - OS " + versionString + "\n" + ecidString);
m_deviceSubtitle->SetLabel("Sorry, jailbreaking is only available via DFU mode - OS " + versionString + "\n" + ecidString);
m_startButton->Enable(false);
} else if (state.isSupported) {
m_deviceTitle->SetLabel(productString);
@@ -256,7 +264,7 @@ void MainPanel::SetDeviceState(const DeviceState& state)
case DeviceMode::Recovery:
if (state.requiresCLI) {
m_deviceTitle->SetLabel(productString);
m_deviceSubtitle->SetLabel("Sorry, jailbreaking is only available via CLI mode.\n" + ecidString);
m_deviceSubtitle->SetLabel("Sorry, jailbreaking is only available via DFU mode.\n" + ecidString);
m_startButton->Enable(false);
} else if (state.isSupported) {
m_deviceTitle->SetLabel(productString);
@@ -269,9 +277,26 @@ void MainPanel::SetDeviceState(const DeviceState& state)
}
break;
case DeviceMode::DFU:
m_deviceTitle->SetLabel("DFU Mode device");
m_deviceSubtitle->SetLabel("Sorry, jailbreaking in DFU is not supported.\n");
m_startButton->Enable(false);
if (state.isSupported) {
m_deviceTitle->SetLabel(productString);
m_deviceSubtitle->SetLabel("Connected in DFU mode.\n" + ecidString);
m_startButton->Enable();
} else {
m_deviceTitle->SetLabel(productString);
m_deviceSubtitle->SetLabel("Sorry, this DFU device is not supported.\n" + ecidString);
m_startButton->Enable(false);
}
break;
case DeviceMode::Pongo:
if (state.isSupported) {
m_deviceTitle->SetLabel(productString);
m_deviceSubtitle->SetLabel("Connected in PongoOS mode.\n" + ecidString);
m_startButton->Enable();
} else {
m_deviceTitle->SetLabel(productString);
m_deviceSubtitle->SetLabel("This PongoOS device is not supported, worth a shot though...\n" + ecidString);
m_startButton->Enable();
}
break;
case DeviceMode::None:
m_deviceTitle->SetLabel(deviceTextString);
+181 -79
View File
@@ -30,6 +30,7 @@
#include "SettingsPanel.hpp"
#include <wx/wx.h>
#include <wx/notebook.h>
#include <wx/mstream.h>
#include <wx/image.h>
#include <wx/bitmap.h>
@@ -41,78 +42,100 @@
#include "../paleinfo.h"
#include "../gen/embedded/logo.h"
auto createTitle = [](wxWindow* parent, const wxString& text)
{
auto* title = new wxStaticText(parent, wxID_ANY, text);
wxFont font = title->GetFont();
font.SetPointSize(font.GetPointSize() - 1);
font.SetWeight(wxFONTWEIGHT_BOLD);
title->SetFont(font);
return title;
};
auto createDescription = [](wxWindow* parent, const wxString& text)
{
auto* description = new wxStaticText(parent, wxID_ANY, text, wxDefaultPosition, wxDefaultSize, wxST_WRAP);
wxFont font = description->GetFont();
font.SetPointSize(font.GetPointSize() - 2);
description->SetFont(font);
return description;
};
SettingsPanel::SettingsPanel(MainFrame* frame, wxWindow* parent)
: DevicePanel(frame, parent)
{
auto* root = new wxBoxSizer(wxHORIZONTAL);
auto* left = new wxBoxSizer(wxVERTICAL);
auto* right = new wxBoxSizer(wxVERTICAL);
wxMemoryInputStream stream(embedded_logo_png, embedded_logo_png_len);
wxImage img(stream, wxBITMAP_TYPE_PNG);
wxBitmap bmp(img);
auto* logo = new wxStaticBitmap(this, wxID_ANY, bmp);
auto* logoText = new wxStaticText(this, wxID_ANY, "Options");
auto* right = new wxBoxSizer(wxVERTICAL);
left->Add(new wxStaticText(this, wxID_ANY,
"You may set the following options. If you don't know what they mean you'll probably have no reason to set them.",
wxDefaultPosition,
wxDefaultSize,
wxST_WRAP
), 0, wxALL, 10);
), 0, wxTOP | wxLEFT | wxRIGHT, 10);
auto* optionSafemode = new wxCheckBox(this, wxID_ANY, "Safe Mode");
auto* optionVerbose = new wxCheckBox(this, wxID_ANY, "Verbose Boot");
auto* optionRevert = new wxCheckBox(this, wxID_ANY, "Restore System");
auto* optionDarkBlockchain = new wxCheckBox(this, wxID_ANY, "Dark Blockchain");
auto* bootArgs = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize);
auto* rootType = new wxRadioBox(
this,
wxID_ANY,
"Jailbreak Type",
wxDefaultPosition,
wxDefaultSize,
2,
(const wxString[]){
"Rootless",
"Rootful"
},
1,
wxRA_SPECIFY_COLS
);
auto* notebook = new wxNotebook(this, wxID_ANY);
auto* generalPage = new wxPanel(notebook);
auto* advancedPage = new wxPanel(notebook);
auto* setupMode = new wxRadioBox(
this,
wxID_ANY,
"Rootful Options",
wxDefaultPosition,
wxDefaultSize,
3,
(const wxString[]){
"Boot",
"Create FakeFS",
"Create BindFS"
},
1,
wxRA_SPECIFY_COLS
);
//
// Controls
//
auto* optionSafemode = new wxCheckBox(generalPage, wxID_ANY, "Safe Mode");
auto* optionVerbose = new wxCheckBox(generalPage, wxID_ANY, "Verbose Boot");
auto* optionRevert = new wxCheckBox(generalPage, wxID_ANY, "Restore System");
auto* optionDarkBlockchain = new wxCheckBox(generalPage, wxID_ANY, "Dark Blockchain");
auto* rootless = new wxRadioButton(generalPage, wxID_ANY, "Rootless", wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
auto* rootful = new wxRadioButton(generalPage, wxID_ANY, "Rootful");
auto* setupBoot = new wxRadioButton(generalPage, wxID_ANY, "Boot", wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
auto* setupFakeFS = new wxRadioButton(generalPage, wxID_ANY, "Create fakeFS");
auto* setupBindFS = new wxRadioButton(generalPage, wxID_ANY, "Create Partial fakeFS");
auto* bootArgs = new wxTextCtrl(advancedPage, wxID_ANY);
auto* optionForceEnableSSV = new wxCheckBox(advancedPage, wxID_ANY, "Force Enable SSV Flag");
//
// Load
//
optionSafemode->SetValue(palerain_flags & palerain_option_safemode);
optionVerbose->SetValue(palerain_flags & palerain_option_verbose_boot);
optionRevert->SetValue(palerain_flags & palerain_option_force_revert);
optionDarkBlockchain->SetValue(palerain_flags & palerain_option_flower_chain);
bootArgs->SetValue(wxString(boot_args, wxConvUTF8));
if (palerain_flags & palerain_option_rootful)
rootType->SetSelection(1);
else
rootType->SetSelection(0);
optionForceEnableSSV->SetValue(palerain_flags & palerain_option_ssv);
rootless->SetValue(!(palerain_flags & palerain_option_rootful));
rootful->SetValue(palerain_flags & palerain_option_rootful);
if (palerain_flags & palerain_option_setup_rootful)
setupMode->SetSelection(1);
setupFakeFS->SetValue(true);
else if (palerain_flags & palerain_option_setup_partial_root)
setupMode->SetSelection(2);
setupBindFS->SetValue(true);
else
setupMode->SetSelection(0);
setupMode->Enable(rootType->GetSelection() == 1);
setupBoot->SetValue(true);
bool isRootful = rootful->GetValue();
setupBoot->Enable(true);
setupFakeFS->Enable(isRootful);
setupBindFS->Enable(isRootful);
optionSafemode->Bind(wxEVT_CHECKBOX, [&](wxCommandEvent& e)
{
@@ -121,6 +144,7 @@ SettingsPanel::SettingsPanel(MainFrame* frame, wxWindow* parent)
else
palerain_flags &= ~palerain_option_safemode;
});
optionVerbose->Bind(wxEVT_CHECKBOX, [&](wxCommandEvent& e)
{
if (e.IsChecked())
@@ -128,6 +152,7 @@ SettingsPanel::SettingsPanel(MainFrame* frame, wxWindow* parent)
else
palerain_flags &= ~palerain_option_verbose_boot;
});
optionRevert->Bind(wxEVT_CHECKBOX, [&](wxCommandEvent& e)
{
if (e.IsChecked())
@@ -135,6 +160,7 @@ SettingsPanel::SettingsPanel(MainFrame* frame, wxWindow* parent)
else
palerain_flags &= ~palerain_option_force_revert;
});
optionDarkBlockchain->Bind(wxEVT_CHECKBOX, [&](wxCommandEvent& e)
{
if (e.IsChecked())
@@ -142,60 +168,136 @@ SettingsPanel::SettingsPanel(MainFrame* frame, wxWindow* parent)
else
palerain_flags &= ~palerain_option_flower_chain;
});
bootArgs->Bind(wxEVT_TEXT, [&](wxCommandEvent& e)
{
wxString value = e.GetString();
if (value.length() > (sizeof(boot_args) - 0x20)) {
if (value.length() > (sizeof(boot_args) - 0x20))
return;
}
snprintf(boot_args, sizeof(boot_args), "%s", value.ToStdString().c_str());
snprintf(boot_args, sizeof(boot_args),
"%s",
value.ToStdString().c_str());
});
rootType->Bind(wxEVT_RADIOBOX, [setupMode](wxCommandEvent& e)
optionForceEnableSSV->Bind(wxEVT_CHECKBOX, [&](wxCommandEvent& e)
{
palerain_flags &= ~(palerain_option_rootless | palerain_option_rootful);
palerain_flags &= ~(palerain_option_setup_rootful | palerain_option_setup_partial_root);
setupMode->Enable(e.GetSelection() == 1);
setupMode->SetSelection(0);
if (e.GetSelection() == 0)
palerain_flags |= palerain_option_rootless;
if (e.IsChecked())
palerain_flags |= palerain_option_ssv;
else
palerain_flags |= palerain_option_rootful;
palerain_flags &= ~palerain_option_ssv;
});
setupMode->Bind(wxEVT_RADIOBOX, [&](wxCommandEvent& e)
rootless->Bind(wxEVT_RADIOBUTTON,
[setupBoot, setupFakeFS, setupBindFS](wxCommandEvent&)
{
palerain_flags &= ~(palerain_option_setup_rootful | palerain_option_setup_partial_root);
palerain_flags &= ~(palerain_option_rootless |
palerain_option_rootful |
palerain_option_setup_rootful |
palerain_option_setup_partial_root);
if (e.GetSelection() == 1)
palerain_flags |= palerain_option_setup_rootful;
else if (e.GetSelection() == 2)
palerain_flags |= palerain_option_setup_partial_root;
palerain_flags |= palerain_option_rootless;
setupBoot->SetValue(true);
setupFakeFS->Enable(false);
setupBindFS->Enable(false);
});
auto* contentRow = new wxBoxSizer(wxHORIZONTAL);
auto* leftColumn = new wxBoxSizer(wxVERTICAL);
auto* rightColumn = new wxBoxSizer(wxVERTICAL);
rootful->Bind(wxEVT_RADIOBUTTON,
[setupFakeFS, setupBindFS](wxCommandEvent&)
{
palerain_flags &= ~(palerain_option_rootless |
palerain_option_rootful);
leftColumn->Add(rootType, 0, wxALL | wxEXPAND, 5);
leftColumn->Add(setupMode, 0, wxALL | wxEXPAND, 5);
palerain_flags |= palerain_option_rootful;
rightColumn->Add(optionSafemode, 0, wxALL, 5);
rightColumn->Add(optionVerbose, 0, wxALL, 5);
rightColumn->Add(optionRevert, 0, wxALL, 5);
rightColumn->Add(optionDarkBlockchain, 0, wxALL, 5);
rightColumn->AddStretchSpacer();
setupFakeFS->Enable(true);
setupBindFS->Enable(true);
});
contentRow->Add(leftColumn, 1, wxEXPAND | wxRIGHT, 10);
contentRow->Add(rightColumn, 1, wxEXPAND | wxLEFT, 10);
setupBoot->Bind(wxEVT_RADIOBUTTON, [](wxCommandEvent&)
{
palerain_flags &= ~(palerain_option_setup_rootful |
palerain_option_setup_partial_root);
});
left->Add(contentRow, 1, wxEXPAND | wxLEFT | wxRIGHT, 10);
left->Add(new wxStaticText(this, wxID_ANY, "Boot Arguments:"), 0, wxALL, 15);
left->Add(bootArgs, 0, wxLEFT | wxRIGHT | wxEXPAND, 30);
left->AddStretchSpacer();
setupFakeFS->Bind(wxEVT_RADIOBUTTON, [&](wxCommandEvent&)
{
palerain_flags &= ~palerain_option_setup_partial_root;
palerain_flags |= palerain_option_setup_rootful;
});
setupBindFS->Bind(wxEVT_RADIOBUTTON, [&](wxCommandEvent&)
{
palerain_flags &= ~palerain_option_setup_rootful;
palerain_flags |= palerain_option_setup_partial_root;
});
//
// General
//
auto* generalSizer = new wxBoxSizer(wxHORIZONTAL);
auto* generalLeft = new wxBoxSizer(wxVERTICAL);
auto* generalRight = new wxBoxSizer(wxVERTICAL);
generalLeft->Add(createTitle(generalPage, "Startup"), 0, wxBOTTOM, 3);
generalLeft->Add(optionSafemode, 0, wxTOP, 7);
generalLeft->Add(optionVerbose, 0, wxTOP , 7);
generalLeft->Add(optionRevert, 0, wxTOP, 7);
generalLeft->Add(optionDarkBlockchain, 0, wxTOP, 7);
generalLeft->AddStretchSpacer();
generalRight->Add(createTitle(generalPage, "Jailbreak Type"), 0, wxBOTTOM, 3);
generalRight->Add(rootless, 0, wxTOP, 7);
generalRight->Add(rootful, 0, wxTOP | wxBOTTOM, 5);
generalRight->Add(createTitle(generalPage, "Startup (Rootful)"), 0, wxTOP | wxBOTTOM, 3);
generalRight->Add(setupBoot, 0, wxTOP, 7);
generalRight->Add(setupFakeFS, 0, wxTOP, 5);
generalRight->Add(setupBindFS, 0, wxTOP, 5);
generalRight->AddStretchSpacer();
generalSizer->Add(generalLeft, 1, wxEXPAND | wxRIGHT | wxLEFT, 10);
generalSizer->Add(generalRight, 1, wxEXPAND | wxLEFT, 10);
generalPage->SetSizer(generalSizer);
//
// Advanced
//
auto* advancedOuterSizer = new wxBoxSizer(wxVERTICAL);
auto* advancedSizer = new wxBoxSizer(wxVERTICAL);
advancedSizer->Add(createTitle(advancedPage, "Boot Arguments"), 0, wxBOTTOM, 3);
advancedSizer->Add(bootArgs, 0, wxTOP | wxBOTTOM | wxEXPAND, 7);
advancedSizer->Add(createTitle(advancedPage, "Advanced"), 0, wxTOP | wxBOTTOM, 3);
advancedSizer->Add(optionForceEnableSSV, 0, wxTOP | wxBOTTOM, 7);
advancedSizer->Add(createDescription(advancedPage, "Forces the jailbreak to detect SSV as being required."), 0, wxLEFT | wxRIGHT, 20);
advancedOuterSizer->Add(advancedSizer, 1, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 10);
advancedPage->SetSizer(advancedOuterSizer);
notebook->AddPage(generalPage, "General", true);
notebook->AddPage(advancedPage, "Advanced");
left->Add(notebook, 1, wxEXPAND | wxALL, 10);
//
// Right side
//
auto* back = new wxButton(this, wxID_ANY, "Back");
right->Add(logo, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP | wxLEFT | wxRIGHT, 10);
right->Add(logoText, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, 5);
right->AddStretchSpacer();