├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── META-INF └── com │ └── google │ └── android │ └── update-binary ├── README.md └── change_os_version.c /.gitignore: -------------------------------------------------------------------------------- 1 | CMakeLists.txt.user 2 | CMakeCache.txt 3 | CMakeFiles 4 | CMakeScripts 5 | Testing 6 | Makefile 7 | cmake_install.cmake 8 | install_manifest.txt 9 | compile_commands.json 10 | CTestTestfile.cmake 11 | _deps 12 | /build 13 | change_os_version 14 | *.zip 15 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | 3 | if (NOT DEFINED NDK_ROOT) 4 | if (DEFINED ENV{NDK_ROOT}) 5 | set(NDK_ROOT "$ENV{NDK_ROOT}") 6 | else () 7 | message(FATAL_ERROR "Please define NDK_ROOT to point to your NDK path!") 8 | endif () 9 | endif () 10 | 11 | find_program(ZIP NAMES zip) 12 | 13 | # Set the tool chain file 14 | set(CMAKE_TOOLCHAIN_FILE ${NDK_ROOT}/build/cmake/android.toolchain.cmake) 15 | set(ANDROID_ABI arm64-v8a) 16 | set(ANDROID_PLATFORM latest) 17 | set(ANDROID_STL none) 18 | set(ANDROID_LD lld) 19 | 20 | add_compile_options(-Wall -Wextra -pedantic -Werror) 21 | 22 | set(DEFAULT_FUTURE_DATE "2099-12" CACHE STRING "Select os_patch_level date.") 23 | option(SELF_PACK_EXECUTABLES "Self-pack executables." ON) 24 | 25 | set(UPDATE_ZIP "backtothefuture-${DEFAULT_FUTURE_DATE}.zip") 26 | 27 | project(BackToTheFuture) 28 | 29 | set(CMAKE_C_FLAGS_RELEASE "-O2 -flto") 30 | set(ANDROID_PIE FALSE) 31 | link_libraries("-static") 32 | 33 | add_executable(change_os_version change_os_version.c) 34 | 35 | if (CMAKE_BUILD_TYPE STREQUAL Release) 36 | add_custom_command( 37 | TARGET change_os_version 38 | POST_BUILD 39 | COMMAND "${ANDROID_TOOLCHAIN_PREFIX}strip" --strip-all change_os_version 40 | COMMENT "Stripping the executables" 41 | VERBATIM 42 | ) 43 | if (SELF_PACK_EXECUTABLES) 44 | include("${CMAKE_ROOT}/Modules/FindSelfPackers.cmake") 45 | if (SELF_PACKER_FOR_EXECUTABLE) 46 | add_custom_command( 47 | TARGET change_os_version 48 | POST_BUILD 49 | COMMAND ${SELF_PACKER_FOR_EXECUTABLE} -9q ${SELF_PACKER_FOR_EXECUTABLE_FLAGS} change_os_version 50 | COMMENT "Packing the executables" 51 | VERBATIM 52 | ) 53 | endif () 54 | endif () 55 | endif () 56 | 57 | if (NOT CMAKE_CURRENT_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) 58 | add_custom_command( 59 | OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/META-INF/com/google/android/update-binary 60 | COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/META-INF/com/google/android/update-binary 61 | ${CMAKE_CURRENT_BINARY_DIR}/META-INF/com/google/android/update-binary 62 | DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/META-INF/com/google/android/update-binary 63 | ) 64 | endif () 65 | 66 | add_custom_target(zip 67 | DEPENDS change_os_version 68 | DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/META-INF/com/google/android/update-binary 69 | COMMAND ${ZIP} ${UPDATE_ZIP} change_os_version META-INF/com/google/android/update-binary 70 | COMMENT "Preparing ${UPDATE_ZIP}" 71 | VERBATIM 72 | ) 73 | 74 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /META-INF/com/google/android/update-binary: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | 3 | ZIPFILE=$3 4 | ZIPNAME=${ZIPFILE##*/} 5 | OUTFD=$2 6 | 7 | screen_width=50 8 | 9 | # Detect real $OUTFD 10 | # 11 | if readlink /proc/$$/fd/$OUTFD 2>/dev/null | grep /tmp >/dev/null; then 12 | OUTFD=0 13 | for FD in $( ls /proc/$$/fd ); do 14 | if readlink /proc/$$/fd/$FD 2>/dev/null | grep pipe >/dev/null; then 15 | if ps | grep " 3 $FD " | grep -v grep >/dev/null; then 16 | OUTFD=$FD 17 | break 18 | fi 19 | fi 20 | done 21 | fi 22 | 23 | ui_print() { 24 | echo -ne "ui_print $1\n" >> /proc/self/fd/$OUTFD 25 | echo -ne "ui_print\n" >> /proc/self/fd/$OUTFD 26 | } 27 | 28 | print_full_bar() { 29 | ui_print "$(printf '%*s\n' $screen_width | tr ' ' '=')" 30 | } 31 | 32 | print_justified() { 33 | local str="$1" 34 | local str_len=${#str} 35 | local padding_len=$(( ($screen_width - $str_len - 2) / 2)) 36 | local ljust="$(printf '%*s' $padding_len)" 37 | local rjust="$(printf '%*s' $(($padding_len + $str_len % 2)))" 38 | 39 | ui_print "=$ljust$str$rjust=" 40 | } 41 | 42 | 43 | ui_print " " 44 | print_full_bar 45 | print_justified "Back to the Future" 46 | print_justified "OS Patch level changer v1.1" 47 | print_justified "of boot and recovery partitions" 48 | print_justified "for Samsung S10/Note10 devices." 49 | print_justified "https://github.com/CruelKernel/" 50 | print_full_bar 51 | ui_print " " 52 | 53 | bl=$(getprop ro.boot.bootloader) 54 | 55 | # Device is first 5 characters of bootloader string. 56 | # 57 | device=${bl:0:$((${#bl} - 8))} 58 | 59 | if echo $device | grep -Ev 'G97([035][FN0]|7[BN])|N97([05][FN0]|6[BN0]|1N)' >/dev/null; then 60 | ui_print " - Unsupported device detected. Installation aborted." 61 | ui_print " " 62 | exit 1 63 | fi 64 | 65 | date="$(echo $ZIPNAME | sed 's/^.*-\(2[0-9]\{3\}-[01][0-9]\).zip$/\1/')" 66 | 67 | if [ "$date" = "$ZIPNAME" ]; then 68 | date="2127-12" 69 | ui_print " - Can't determine os_patch_level date" 70 | ui_print " - from filename '$ZIPNAME'." 71 | ui_print " - Max possible date $date will be used." 72 | else 73 | ui_print " - Detected date from zip filename: $date." 74 | fi 75 | 76 | unzip -d /tmp -o $ZIPFILE change_os_version 77 | chmod +x /tmp/change_os_version 78 | 79 | ui_print " - Patching boot ..." 80 | /tmp/change_os_version /dev/block/by-name/boot same $date 2>&1 | 81 | sed 's/^\(.*\)$/ui_print - - \1\n/' >> /proc/self/fd/$OUTFD 82 | ui_print " " 83 | ui_print " - Patching recovery ..." 84 | /tmp/change_os_version /dev/block/by-name/recovery same $date 2>&1 | 85 | sed 's/^\(.*\)$/ui_print - - \1\n/' >> /proc/self/fd/$OUTFD 86 | 87 | rm -f /tmp/change_os_version 88 | 89 | ui_print " " 90 | ui_print " - Finished." 91 | ui_print " " 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Back to the Future 2 | 3 | OS Patch Level changer for boot and recovery partitions. Flash in TWRP. You can set desired date in filename. Date format: YYYY-MM. For example: backtothefuture-2021-12.zip If there will be no date in the filename, max possible date 2127-12 will be used. If you select a wrong date, then don't reboot, rename the zipfile and flash it again. 4 | 5 | Downloads: https://github.com/CruelKernel/backtothefuture/releases 6 | 7 | If someone wants to know more about why it's not possible to rollback to normal date, here is the official documentation: https://source.android.com/security/keystore/version-binding#hal-changes. Short answer: because all your security keys are cryptographically updated with new os_patch_level date once you boot with "new date" kernel. 8 | 9 | So, once you installed a kernel with os_patch_level in future you are doomed to use greater or equal os_patch_level date for all your next kernels. However, full wipe will help. 10 | -------------------------------------------------------------------------------- /change_os_version.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define BOOT_MAGIC_SIZE 8 17 | #define BOOT_IMAGE_HEADER_V1_SIZE 1648 18 | #define BOOT_IMAGE_HEADER_V2_SIZE 1660 19 | 20 | #define HEADER_VERSION_OFFSET ( \ 21 | sizeof(uint8_t) * BOOT_MAGIC_SIZE + \ 22 | 8 * sizeof(uint32_t) \ 23 | ) 24 | #define OS_VERSION_OFFSET_V0 (HEADER_VERSION_OFFSET + sizeof(uint32_t)) 25 | #define OS_VERSION_OFFSET_V1 OS_VERSION_OFFSET_V0 26 | #define OS_VERSION_OFFSET_V2 OS_VERSION_OFFSET_V0 27 | #define OS_VERSION_OFFSET_V3 (HEADER_VERSION_OFFSET - 6 * sizeof(uint32_t)) 28 | 29 | typedef union __attribute__((packed)) { 30 | uint32_t version; 31 | struct { 32 | unsigned os_patch_level:11; 33 | unsigned os_version:21; 34 | }; 35 | struct { 36 | unsigned month:4; 37 | unsigned year:7; 38 | unsigned c:7; 39 | unsigned b:7; 40 | unsigned a:7; 41 | }; 42 | } os_version_t; 43 | 44 | static bool stop_on(bool print_errno, bool cond, const char *message, ...) 45 | { 46 | if (!cond) 47 | return false; 48 | 49 | va_list args; 50 | va_start(args, message); 51 | vfprintf(stderr, message, args); 52 | va_end(args); 53 | if (print_errno) 54 | fprintf(stderr, ": %s", strerror(errno)); 55 | fprintf(stderr, "\n"); 56 | exit(EXIT_FAILURE); 57 | 58 | return true; 59 | } 60 | 61 | #define stopx(cond, ...) stop_on(false, cond, __VA_ARGS__) 62 | #define stop(cond, ...) stop_on(true, cond, __VA_ARGS__) 63 | 64 | static bool check_cond(bool print_errno, bool cond, const char *message, ...) 65 | { 66 | if (!cond) 67 | return false; 68 | 69 | va_list args; 70 | va_start(args, message); 71 | vfprintf(stderr, message, args); 72 | va_end(args); 73 | if (print_errno) 74 | fprintf(stderr, ": %s", strerror(errno)); 75 | fprintf(stderr, "\n"); 76 | 77 | return true; 78 | } 79 | 80 | #define checkx(cond, ...) check_cond(false, cond, __VA_ARGS__) 81 | #define check(cond, ...) check_cond(true, cond, __VA_ARGS__) 82 | 83 | 84 | static inline uint32_t get_header_version(uint8_t *addr) 85 | { 86 | return *(uint32_t *)(addr + HEADER_VERSION_OFFSET); 87 | } 88 | 89 | static inline os_version_t get_os_version(uint8_t *addr) 90 | { 91 | os_version_t v; 92 | uint32_t hdr_ver = get_header_version(addr); 93 | 94 | switch (hdr_ver) { 95 | case 0: 96 | case 1: 97 | case 2: 98 | v.version = *(uint32_t *)(addr + OS_VERSION_OFFSET_V2); 99 | break; 100 | case 3: 101 | v.version = *(uint32_t *)(addr + OS_VERSION_OFFSET_V3); 102 | break; 103 | default: 104 | errx(1, "Unsupported header version %u", hdr_ver); 105 | break; 106 | } 107 | return v; 108 | } 109 | 110 | static inline void set_os_version(uint8_t *addr, os_version_t v) 111 | { 112 | uint32_t hdr_ver = get_header_version(addr); 113 | 114 | switch (hdr_ver) { 115 | case 0: 116 | case 1: 117 | case 2: 118 | *(uint32_t *)(addr + OS_VERSION_OFFSET_V2) = v.version; 119 | break; 120 | case 3: 121 | *(uint32_t *)(addr + OS_VERSION_OFFSET_V3) = v.version; 122 | break; 123 | default: 124 | errx(1, "Unsupported header version %u", hdr_ver); 125 | break; 126 | } 127 | } 128 | 129 | static uint8_t *mmap_boot_image(const char *file, int flags) 130 | { 131 | uint8_t *addr; 132 | uint32_t header_version; 133 | struct stat st; 134 | int mmap_flags = PROT_READ; 135 | size_t block_size; 136 | 137 | int fd = open(file, flags); 138 | stop(fd < 0, "open %s failed", file); 139 | 140 | if (flags == O_RDWR) 141 | mmap_flags |= PROT_WRITE; 142 | 143 | stop(fstat(fd, &st) < 0, "stat %s failed", file); 144 | stopx(!(S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) && 145 | st.st_size < BOOT_IMAGE_HEADER_V2_SIZE, 146 | "%s is too small", file); 147 | stopx(S_ISCHR(st.st_mode), "%s is not a block device", file); 148 | 149 | if (S_ISBLK(st.st_mode)) { 150 | stop(ioctl(fd, BLKGETSIZE64, &block_size) < 0, 151 | "%s can't determine block device size", file); 152 | stopx(block_size < BOOT_IMAGE_HEADER_V2_SIZE, 153 | "%s is too small", file); 154 | } 155 | 156 | addr = mmap(NULL, BOOT_IMAGE_HEADER_V2_SIZE, mmap_flags, 157 | MAP_SHARED, fd, 0); 158 | stop(addr == MAP_FAILED, "mmap %s failed", file); 159 | close(fd); 160 | 161 | stopx(strncmp((const char *)addr, "ANDROID!", 8), 162 | "%s has incorrect magic number, not an android boot image", 163 | file 164 | ); 165 | 166 | header_version = get_header_version(addr); 167 | stopx(header_version > 3, 168 | "%s unsupported header version (%u)", 169 | file, header_version 170 | ); 171 | 172 | return addr; 173 | } 174 | 175 | int main(int argc, char *argv[]) 176 | { 177 | uint8_t *addr; 178 | const char *file, *os_version, *os_patch_level; 179 | char *delim = NULL; 180 | int year, month; 181 | int a, b, c; 182 | os_version_t curv, newv; 183 | bool preserve_os_version = false; 184 | bool preserve_os_patch_level = false; 185 | 186 | stopx(argc != 4, 187 | "Usage: %s ", 188 | argv[0]); 189 | 190 | file = argv[1]; 191 | os_version = argv[2]; 192 | os_patch_level = argv[3]; 193 | 194 | if (!strcmp(os_version, "same")) { 195 | preserve_os_version = true; 196 | } else { 197 | // Format: a.b.c 198 | for (const char *p = os_version; *p != '\0'; ++p) { 199 | stopx(!(isdigit(*p) || *p == '.'), 200 | "Incorrect os_version '%s'. Format: a.b.c", 201 | os_version); 202 | } 203 | a = strtol(os_version, &delim, 10); 204 | stopx(*delim != '.', 205 | "Incorrect os_version '%s'. Format: a.b.c", os_version); 206 | b = strtol(delim + 1, &delim, 10); 207 | stopx(*delim != '.', 208 | "Incorrect os_version '%s'. Format: a.b.c", os_version); 209 | c = strtol(delim + 1, NULL, 10); 210 | stopx(!(0 <= a && a <= 127 && 211 | 0 <= b && b <= 127 && 212 | 0 <= c && c <= 127), 213 | "Incorrect os_version '%s'. Format: a.b.c", os_version); 214 | } 215 | 216 | if (!strcmp(os_patch_level, "same")) { 217 | preserve_os_patch_level = true; 218 | } else { 219 | // Format: YYYY-MM 220 | stopx(strlen(os_patch_level) != 7 || 221 | os_patch_level[4] != '-' || 222 | !isdigit(os_patch_level[0]) || 223 | !isdigit(os_patch_level[1]) || 224 | !isdigit(os_patch_level[2]) || 225 | !isdigit(os_patch_level[3]) || 226 | !isdigit(os_patch_level[5]) || 227 | !isdigit(os_patch_level[6]), 228 | "Incorrent os_patch_level '%s'. Format: YYYY-MM", 229 | os_patch_level); 230 | 231 | year = atoi(os_patch_level); 232 | month = atoi(os_patch_level + 5); 233 | 234 | stopx(!(2000 <= year && year <= 2127), 235 | "Incorrect year: %ld (2000 <= year <= 2127)", year); 236 | stopx(!(1 <= month && month <= 12), 237 | "Incorrect month: %ld (01 <= month <= 12)", month); 238 | } 239 | 240 | addr = mmap_boot_image(file, O_RDWR); 241 | 242 | curv = get_os_version(addr); 243 | printf("Current OS version:\t%u.%u.%u %u-%02u\n", 244 | curv.a, curv.b, curv.c, 245 | curv.year + 2000, curv.month); 246 | 247 | if (preserve_os_version) { 248 | newv.os_version = curv.os_version; 249 | } else { 250 | newv.a = a; 251 | newv.b = b; 252 | newv.c = c; 253 | } 254 | 255 | if (preserve_os_patch_level) { 256 | newv.os_patch_level = curv.os_patch_level; 257 | } else { 258 | newv.year = (year - 2000); 259 | newv.month = month; 260 | } 261 | 262 | if (curv.version != newv.version) { 263 | printf("New OS version:\t\t%u.%u.%u %u-%02u\n", 264 | newv.a, newv.b, newv.c, 265 | newv.year + 2000, newv.month); 266 | 267 | checkx(curv.os_version > newv.os_version, 268 | "warn: new os_version is lower than current" 269 | ); 270 | 271 | checkx(curv.os_patch_level > newv.os_patch_level, 272 | "warn: new os_patch_level version is lower than current" 273 | ); 274 | 275 | set_os_version(addr, newv); 276 | 277 | check(msync(addr, BOOT_IMAGE_HEADER_V2_SIZE, MS_SYNC) < 0, 278 | "msync failed"); 279 | } else { 280 | printf("The dates are the same. Nothing to be done.\n"); 281 | } 282 | 283 | munmap(addr, BOOT_IMAGE_HEADER_V2_SIZE); 284 | 285 | return 0; 286 | } 287 | --------------------------------------------------------------------------------