-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
change_os_version: scan os_patch_level on boot/recovery images
Signed-off-by: Denis Efremov <[email protected]>
- Loading branch information
Showing
3 changed files
with
319 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
cmake_minimum_required(VERSION 3.12) | ||
|
||
if (NOT DEFINED NDK_ROOT) | ||
if (DEFINED ENV{NDK_ROOT}) | ||
set(NDK_ROOT "$ENV{NDK_ROOT}") | ||
else () | ||
message(FATAL_ERROR "Please define NDK_ROOT to point to your NDK path!") | ||
endif () | ||
endif () | ||
|
||
find_program(ZIP NAMES zip) | ||
|
||
# Set the tool chain file | ||
set(CMAKE_TOOLCHAIN_FILE ${NDK_ROOT}/build/cmake/android.toolchain.cmake) | ||
set(ANDROID_ABI arm64-v8a) | ||
set(ANDROID_PLATFORM latest) | ||
set(ANDROID_STL none) | ||
set(ANDROID_LD lld) | ||
|
||
add_compile_options(-Wall -Wextra -pedantic -Werror) | ||
|
||
set(DEFAULT_FUTURE_DATE "2099-12" CACHE STRING "Select os_patch_level date.") | ||
option(SELF_PACK_EXECUTABLES "Self-pack executables." ON) | ||
|
||
set(UPDATE_ZIP "backtothefuture-${DEFAULT_FUTURE_DATE}.zip") | ||
|
||
project(BackToTheFuture) | ||
|
||
set(CMAKE_C_FLAGS_RELEASE "-O2 -flto") | ||
set(ANDROID_PIE FALSE) | ||
link_libraries("-static") | ||
|
||
add_executable(change_os_version change_os_version.c) | ||
|
||
if (CMAKE_BUILD_TYPE STREQUAL Release) | ||
add_custom_command( | ||
TARGET change_os_version | ||
POST_BUILD | ||
COMMAND "${ANDROID_TOOLCHAIN_PREFIX}strip" --strip-all change_os_version | ||
COMMENT "Stripping the executables" | ||
VERBATIM | ||
) | ||
if (SELF_PACK_EXECUTABLES) | ||
include("${CMAKE_ROOT}/Modules/FindSelfPackers.cmake") | ||
if (SELF_PACKER_FOR_EXECUTABLE) | ||
add_custom_command( | ||
TARGET change_os_version | ||
POST_BUILD | ||
COMMAND ${SELF_PACKER_FOR_EXECUTABLE} -9q ${SELF_PACKER_FOR_EXECUTABLE_FLAGS} change_os_version | ||
COMMENT "Packing the executables" | ||
VERBATIM | ||
) | ||
endif () | ||
endif () | ||
endif () | ||
|
||
if (NOT CMAKE_CURRENT_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) | ||
add_custom_command( | ||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/META-INF/com/google/android/update-binary | ||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/META-INF/com/google/android/update-binary | ||
${CMAKE_CURRENT_BINARY_DIR}/META-INF/com/google/android/update-binary | ||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/META-INF/com/google/android/update-binary | ||
) | ||
endif () | ||
|
||
add_custom_target(zip | ||
DEPENDS change_os_version | ||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/META-INF/com/google/android/update-binary | ||
COMMAND ${ZIP} ${UPDATE_ZIP} change_os_version META-INF/com/google/android/update-binary | ||
COMMENT "Preparing ${UPDATE_ZIP}" | ||
VERBATIM | ||
) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
#!/sbin/sh | ||
|
||
ZIPFILE=$3 | ||
ZIPNAME=${ZIPFILE##*/} | ||
OUTFD=$2 | ||
|
||
scr_wdth=50 | ||
|
||
# Detect real $OUTFD | ||
# | ||
if readlink /proc/$$/fd/$OUTFD 2>/dev/null | grep /tmp >/dev/null; then | ||
OUTFD=0 | ||
for FD in $( ls /proc/$$/fd ); do | ||
if readlink /proc/$$/fd/$FD 2>/dev/null | grep pipe >/dev/null; then | ||
if ps | grep " 3 $FD " | grep -v grep >/dev/null; then | ||
OUTFD=$FD | ||
break | ||
fi | ||
fi | ||
done | ||
fi | ||
|
||
ui_print() { | ||
echo -ne "ui_print $1\n" >> /proc/self/fd/$OUTFD | ||
echo -ne "ui_print\n" >> /proc/self/fd/$OUTFD | ||
} | ||
|
||
print_full_bar() { | ||
ui_print "$(printf '%*s\n' $scr_wdth | tr ' ' '=')" | ||
} | ||
|
||
print_justified() { | ||
local str="$1" | ||
local str_len=${#str} | ||
local padding_len=$(( ($scr_wdth - $str_len - 2) / 2)) | ||
local ljust="$(printf '%*s' $padding_len)" | ||
local rjust="$(printf '%*s' $(($padding_len + $str_len % 2)))" | ||
|
||
ui_print "=$ljust$str$rjust=" | ||
} | ||
|
||
|
||
ui_print " " | ||
print_full_bar | ||
print_justified "Back to the Future" | ||
print_justified "OS Patch level changer v1.0" | ||
print_justified "of boot and recovery partitions" | ||
print_justified "for Samsung S10/Note10 devices." | ||
print_justified "https://github.com/CruelKernel/" | ||
print_full_bar | ||
ui_print " " | ||
|
||
bl=$(getprop ro.boot.bootloader) | ||
|
||
# Device is first 5 characters of bootloader string. | ||
# | ||
device=${bl:0:$((${#bl} - 8))} | ||
|
||
if echo $device | grep -Ev 'G97([035][FN0]|7[BN])|N97([05][FN0]|6[BN0]|1N)' >/dev/null; then | ||
ui_print " - Unsupported device detected. Installation aborted." | ||
ui_print " " | ||
exit 1 | ||
fi | ||
|
||
date="$(echo $ZIPNAME | sed 's/^.*-\(2[0-9]\{3\}-[01][0-9]\).zip$/\1/')" | ||
|
||
if [ "$date" = "$ZIPNAME" ]; then | ||
date="2127-12" | ||
ui_print " - Can't determine os_patch_level date" | ||
ui_print " - from filename '$ZIPNAME'." | ||
ui_print " - Max possible date $date will be used." | ||
else | ||
ui_print " - Detected date from zip filename: $date." | ||
fi | ||
|
||
unzip -d /tmp -o $ZIPFILE change_os_version | ||
chmod +x /tmp/change_os_version | ||
|
||
ui_print " - Patching boot ..." | ||
/tmp/change_os_version /dev/block/by-name/boot same $date 2>&1 | | ||
sed 's/^\(.*\)$/ui_print - - \1\n/' >> /proc/self/fd/$OUTFD | ||
ui_print " " | ||
ui_print " - Patching recovery ..." | ||
/tmp/change_os_version /dev/block/by-name/recovery same $date 2>&1 | | ||
sed 's/^\(.*\)$/ui_print - - \1\n/' >> /proc/self/fd/$OUTFD | ||
|
||
rm -f /tmp/change_os_version | ||
|
||
ui_print " " | ||
ui_print " - Finished." | ||
ui_print " " |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
#include <errno.h> | ||
#include <stdbool.h> | ||
#include <stdint.h> | ||
#include <ctype.h> | ||
#include <fcntl.h> | ||
#include <unistd.h> | ||
#include <stdlib.h> | ||
#include <sys/mman.h> | ||
#include <stdarg.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
|
||
#define BOOT_IMAGE_HEADER_V1_SIZE 1648 | ||
#define BOOT_IMAGE_HEADER_V2_SIZE 1660 | ||
|
||
typedef union __attribute__((packed)) { | ||
uint32_t version; | ||
struct { | ||
unsigned os_patch_level:11; | ||
unsigned os_version:21; | ||
}; | ||
struct { | ||
unsigned month:4; | ||
unsigned year:7; | ||
unsigned c:7; | ||
unsigned b:7; | ||
unsigned a:7; | ||
}; | ||
} os_version_t; | ||
|
||
|
||
static inline void check(bool cond, const char *message, ...) | ||
{ | ||
if (cond) { | ||
va_list args; | ||
va_start(args, message); | ||
vfprintf(stderr, message, args); | ||
va_end(args); | ||
exit(EXIT_FAILURE); | ||
} | ||
} | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
int fd; | ||
uint32_t *addr; | ||
const char *file, *os_version, *os_patch_level; | ||
char *delim = NULL; | ||
int year, month; | ||
int a, b, c; | ||
os_version_t curv, newv; | ||
bool preserve_os_version = false; | ||
bool preserve_os_patch_level = false; | ||
|
||
check(argc != 4, "Usage: %s <file> <os_version|same> <os_patch_level|same>\n", argv[0]); | ||
file = argv[1]; | ||
os_version = argv[2]; | ||
os_patch_level = argv[3]; | ||
|
||
if (!strcmp(os_version, "same")) { | ||
preserve_os_version = true; | ||
} else { | ||
// Format: a.b.c | ||
for (const char *p = os_version; *p != '\0'; ++p) { | ||
check(!(isdigit(*p) || *p == '.'), | ||
"Incorrect os_version '%s'. Format: a.b.c\n", os_version); | ||
} | ||
a = strtol(os_version, &delim, 10); | ||
check(*delim != '.', "Incorrect os_version '%s'. Format: a.b.c\n", os_version); | ||
b = strtol(delim + 1, &delim, 10); | ||
check(*delim != '.', "Incorrect os_version '%s'. Format: a.b.c\n", os_version); | ||
c = strtol(delim + 1, NULL, 10); | ||
check(!(0 <= a && a <= 127 && | ||
0 <= b && b <= 127 && | ||
0 <= c && c <= 127), | ||
"Incorrect os_version '%s'. Format: a.b.c\n", os_version); | ||
} | ||
|
||
|
||
if (!strcmp(os_patch_level, "same")) { | ||
preserve_os_patch_level = true; | ||
} else { | ||
// Format: YYYY-MM | ||
check(strlen(os_patch_level) != 7 || | ||
os_patch_level[4] != '-' || | ||
!isdigit(os_patch_level[0]) || | ||
!isdigit(os_patch_level[1]) || | ||
!isdigit(os_patch_level[2]) || | ||
!isdigit(os_patch_level[3]) || | ||
!isdigit(os_patch_level[5]) || | ||
!isdigit(os_patch_level[6]), | ||
"Incorrent os_patch_level '%s'. Format: YYYY-MM\n", os_patch_level); | ||
|
||
year = atoi(os_patch_level); | ||
month = atoi(os_patch_level + 5); | ||
|
||
check(!(2000 <= year && year <= 2127), | ||
"Incorrect year: %ld (2000 <= year <= 2127)\n", year); | ||
check(!(1 <= month && month <= 12), | ||
"Incorrect month: %ld (01 <= month <= 12)\n", month); | ||
} | ||
|
||
fd = open(file, O_RDWR); | ||
check(fd < 0, "open %s failed: %s\n", file, strerror(errno)); | ||
|
||
addr = mmap(NULL, BOOT_IMAGE_HEADER_V1_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); | ||
check(addr == MAP_FAILED, "mmap %s failed: %s\n", file, strerror(errno)); | ||
|
||
check(strncmp((const char *)addr, "ANDROID!", 8), | ||
"Incorrect magic number, not a boot file.\n"); | ||
|
||
curv.version = *(addr + 11); | ||
printf("Current OS version:\t%u.%u.%u %u-%02u\n", | ||
curv.a, curv.b, curv.c, | ||
curv.year + 2000, curv.month); | ||
|
||
if (preserve_os_version) { | ||
newv.os_version = curv.os_version; | ||
} else { | ||
newv.a = a; | ||
newv.b = b; | ||
newv.c = c; | ||
} | ||
|
||
if (preserve_os_patch_level) { | ||
newv.os_patch_level = curv.os_patch_level; | ||
} else { | ||
newv.year = (year - 2000); | ||
newv.month = month; | ||
} | ||
|
||
if (curv.version != newv.version) { | ||
printf("New OS version:\t\t%u.%u.%u %u-%02u\n", | ||
newv.a, newv.b, newv.c, | ||
newv.year + 2000, newv.month); | ||
|
||
if (curv.os_version > newv.os_version) { | ||
fprintf(stderr, "warn: new os_version is lower than current\n"); | ||
} | ||
|
||
if (curv.os_patch_level > newv.os_patch_level) { | ||
fprintf(stderr, "warn: new os_patch_level version is lower than current\n"); | ||
} | ||
|
||
*(addr + 11) = newv.version; | ||
check(msync(addr, BOOT_IMAGE_HEADER_V1_SIZE, MS_SYNC) < 0, "msync failed: %s\n", strerror(errno)); | ||
} else { | ||
printf("The dates are the same. Nothing to be done.\n"); | ||
} | ||
|
||
check(munmap(addr, BOOT_IMAGE_HEADER_V1_SIZE) < 0, "munmap failed: %s\n", strerror(errno)); | ||
check(close(fd) < 0, "close failed: %s\n", strerror(errno)); | ||
|
||
return 0; | ||
} |