├── Android.mk ├── defines.h ├── extract_elf_ramdisk.c ├── libcrecovery_common.h └── system.c /Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | include $(CLEAR_VARS) 3 | 4 | LOCAL_SRC_FILES:= \ 5 | extract_elf_ramdisk.c \ 6 | system.c 7 | LOCAL_FORCE_STATIC_EXECUTABLE := true 8 | LOCAL_STATIC_LIBRARIES = libelf libc libm 9 | LOCAL_C_INCLUDES := external/elfutils/libelf 10 | LOCAL_CFLAGS:= -g -c -W 11 | LOCAL_MODULE:=extract_elf_ramdisk 12 | LOCAL_MODULE_TAGS:= eng 13 | LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES 14 | LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities 15 | include $(BUILD_EXECUTABLE) 16 | 17 | -------------------------------------------------------------------------------- /defines.h: -------------------------------------------------------------------------------- 1 | #undef _PATH_BSHELL 2 | #define _PATH_BSHELL "/sbin/sh" 3 | -------------------------------------------------------------------------------- /extract_elf_ramdisk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This binary extracts the ramdisk from a Sony elf style boot or 3 | * recovery image, gunzips it, checks to make sure that it is not a 4 | * stock recovery ramdisk, and then places it in the destination. 5 | * The goal is to use the FOTA partition to store a recovery image 6 | * and extract the ramdisk to be used during boot on Sony devices that 7 | * typically have a recovery-in-boot setup due to Sony disabling the 8 | * ability to boot the FOTA partition on unlocked devices. This binary 9 | * allows the recovery ramdisk to be separate from the boot partition 10 | * so that users can decide what recovery they want to have instead of 11 | * being stuck with whatever recovery their kernel or ROM maker decided 12 | * to include in the boot image. 13 | * 14 | * This program is free software; you can redistribute it and/or modify 15 | * it under the terms of the GNU General Public License version 2 and 16 | * only version 2 as published by the Free Software Foundation. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program; if not, write to the Free Software 25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26 | * 02110-1301, USA. 27 | * 28 | * The code was written from scratch by Dees_Troy dees_troy at 29 | * yahoo 30 | * 31 | * Copyright (c) 2013 32 | */ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include "gelf.h" 41 | #include "libcrecovery_common.h" 42 | 43 | #define ELF_RAMDISK_LOCATION 2 // Ramdisk is the second file in the image 44 | #define EER_DEFAULT_TMP "/tmp" // Scatch folder default location 45 | #define EER_TMP_RAMDISK_GZ "ramdisk.gz" // temporary ramdisk gzip file name 46 | #define EER_TMP_RAMDISK_CPIO "ramdisk.cpio" // temporary ramdisk cpio file name 47 | #define EER_SEARCH_STRING "fota-ua" // String to search to determine if the 48 | // ramdisk is a stock Sony FOTA ramdisk 49 | #ifndef PATH_MAX 50 | #define PATH_MAX 255 51 | #endif 52 | 53 | char input_filename[PATH_MAX], output_filename[PATH_MAX], tmp_dir[PATH_MAX]; 54 | int has_input = 0, has_output = 0, dont_unzip = 0, check_ramdisk = 0; 55 | int use_dump_image = 0, arg_error = 0, ramdisk_loc = ELF_RAMDISK_LOCATION; 56 | 57 | int path_exists(char* path) { 58 | // Check to see if the path exists 59 | struct stat st; 60 | if (stat(path, &st) != 0) 61 | return 0; 62 | else 63 | return -1; 64 | } 65 | 66 | int scan_file_for_data(char *filename, unsigned char *data, int data_size, 67 | unsigned long start_location, unsigned long *data_address) { 68 | FILE *pFile; 69 | unsigned long lSize; 70 | unsigned char *buffer, *last_needle = NULL; 71 | unsigned char needle[data_size]; 72 | size_t result; 73 | int i, return_val = 0; 74 | 75 | pFile = fopen(filename, "rb"); 76 | if(pFile==NULL){ 77 | printf("Unabled to open file '%s'.\nFailed\n", filename); 78 | exit(-1); 79 | } 80 | 81 | fseek (pFile , 0 , SEEK_END); 82 | lSize = ftell(pFile); 83 | rewind(pFile); 84 | 85 | buffer = (unsigned char*)malloc(sizeof(unsigned char) * lSize); 86 | if(buffer == NULL){ 87 | printf("Memory allocation error on '%s'!\nFailed\n", filename); 88 | exit(-1); 89 | } 90 | 91 | result = fread(buffer, 1, lSize, pFile); 92 | if (result != lSize) { 93 | printf("Error reading file '%s'\nFailed\n", filename); 94 | exit(-1); 95 | } 96 | 97 | for (i=0; i '%s'", output, 267 | output2); 268 | __system(command); 269 | unlink(output); 270 | printf("Uncompressed ramdisk written to '%s'\n", output2); 271 | if (check_ramdisk) { 272 | printf("Checking ramdisk to ensure it is not a stock Sony "); 273 | printf("recovery.\n"); 274 | printf(" (Checking for %s)\n", EER_SEARCH_STRING); 275 | // Find the ramdisk offset table 276 | unsigned char needle[7] = EER_SEARCH_STRING; 277 | return_val = scan_file_for_data(output2, needle, sizeof(needle), 0, 278 | &fota_location); 279 | if (return_val < 0) { 280 | printf("This is not a stock Sony recovery ramdisk.\n"); 281 | copy_file_part(output2, output_filename, 0, 0); 282 | printf("Ramdisk copied to '%s'\nDONE!\n", output_filename); 283 | } else { 284 | printf("This is a stock Sony recovery ramdisk.\n"); 285 | printf("Ramdisk NOT copied to '%s'\n", output_filename); 286 | } 287 | unlink(output2); 288 | } else { 289 | printf("DONE!\n"); 290 | } 291 | } else { 292 | printf("Ramdisk copied to '%s'\nDONE!\n", output_filename); 293 | } 294 | } 295 | 296 | void print_usage() { 297 | printf("ELF Image Ramdisk Extractor by Dees_Troy\n"); 298 | printf("Usage:\n\nRequired:\n"); 299 | printf(" -i Specifies the .elf file to read the "); 300 | printf("ramdisk from (required)\n"); 301 | printf(" -o Specifies the final target of the .cpio "); 302 | printf("file (required)\n\n"); 303 | printf("Optional:\n"); 304 | printf(" -t Specifies directory to use for scratch\n"); 305 | printf(" space (uses %s if not specified)\n", 306 | EER_DEFAULT_TMP); 307 | printf(" -u Use dump_image to extract image (may be\n"); 308 | printf(" needed on MTD devices)\n"); 309 | printf(" -d Do not gunzip\n"); 310 | printf(" -c Check ramdisk for stock recovery (cannot\n"); 311 | printf(" be used with -d)\n\n"); 312 | printf(" -0 Extract kernel\n"); 313 | printf(" -2 Extract rpm\n"); 314 | printf("If a stock recovery ramdisk is found, the ramdisk will not be\n"); 315 | printf("copied to the output filename.\n"); 316 | } 317 | 318 | int main(int argc, char** argv) { 319 | int index; 320 | 321 | umask(0); 322 | 323 | if (argc < 5) { 324 | print_usage(); 325 | exit(-1); 326 | } 327 | 328 | strcpy(tmp_dir, EER_DEFAULT_TMP); 329 | 330 | for (index = 1; index < argc; index++) { 331 | if (strlen(argv[index]) != 2) { 332 | arg_error = 1; 333 | index = argc; 334 | } else if (strncmp(argv[index], "-i", 2) == 0) { 335 | // Input filename 336 | if (index == argc - 1) { 337 | arg_error = 1; 338 | printf("Missing input filename.\n\n"); 339 | index = argc; 340 | } else if (strlen(argv[index + 1]) > PATH_MAX - 1) { 341 | arg_error = 2; 342 | index = argc; 343 | } else { 344 | index++; 345 | strcpy(input_filename, argv[index]); 346 | if (!path_exists(input_filename)) { 347 | arg_error = 4; 348 | printf("Input filename '%s' does not exist.\n\n", 349 | input_filename); 350 | index = argc; 351 | } 352 | } 353 | } else if (strncmp(argv[index], "-o", 2) == 0) { 354 | // Output filename 355 | if (index == argc - 1) { 356 | arg_error = 1; 357 | printf("Missing output filename.\n\n"); 358 | index = argc; 359 | } else if (strlen(argv[index + 1]) > PATH_MAX - 1) { 360 | arg_error = 2; 361 | index = argc; 362 | } else { 363 | index++; 364 | strcpy(output_filename, argv[index]); 365 | } 366 | } else if (strncmp(argv[index], "-t", 2) == 0) { 367 | // Temp folder specified 368 | if (index == argc - 1) { 369 | arg_error = 1; 370 | printf("Missing temp directory parameter.\n\n"); 371 | index = argc; 372 | } else if (strlen(argv[index + 1]) > PATH_MAX - 1) { 373 | arg_error = 2; 374 | index = argc; 375 | } else { 376 | index++; 377 | strcpy(tmp_dir, argv[index]); 378 | if (!path_exists(tmp_dir)) { 379 | arg_error = 5; 380 | printf("Temp directory '%s' does not exist.\n\n", 381 | tmp_dir); 382 | index = argc; 383 | } 384 | } 385 | } else if (strncmp(argv[index], "-d", 2) == 0) { 386 | dont_unzip = 1; 387 | } else if (strncmp(argv[index], "-c", 2) == 0) { 388 | check_ramdisk = 1; 389 | } else if (strncmp(argv[index], "-u", 2) == 0) { 390 | use_dump_image = 1; 391 | } else if (strncmp(argv[index], "-0", 2) == 0) { 392 | ramdisk_loc = 1; 393 | } else if (strncmp(argv[index], "-2", 2) == 0) { 394 | ramdisk_loc = 3; 395 | } else { 396 | arg_error = 3; 397 | printf("Invalid argument '%s'.\n\n", argv[index]); 398 | index = argc; 399 | } 400 | } 401 | 402 | if (arg_error != 0) { 403 | print_usage(); 404 | exit(-1); 405 | } else { 406 | extract_ramdisk(); 407 | exit(0); 408 | } 409 | } 410 | -------------------------------------------------------------------------------- /libcrecovery_common.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBCRECOVERY_COMMON_H 2 | #define LIBCRECOVERY_COMMON_H 3 | 4 | #include 5 | 6 | int __system(const char *command); 7 | FILE * __popen(const char *program, const char *type); 8 | int __pclose(FILE *iop); 9 | 10 | #endif -------------------------------------------------------------------------------- /system.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: system.c,v 1.8 2005/08/08 08:05:37 espie Exp $ */ 2 | /* 3 | * Copyright (c) 1988 The Regents of the University of California. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 3. Neither the name of the University nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 | * SUCH DAMAGE. 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include "defines.h" 39 | 40 | extern char **environ; 41 | 42 | int 43 | __system(const char *command) 44 | { 45 | pid_t pid; 46 | sig_t intsave, quitsave; 47 | sigset_t mask, omask; 48 | int pstat; 49 | char *argp[] = {"sh", "-c", NULL, NULL}; 50 | 51 | if (!command) /* just checking... */ 52 | return(1); 53 | 54 | argp[2] = (char *)command; 55 | 56 | sigemptyset(&mask); 57 | sigaddset(&mask, SIGCHLD); 58 | sigprocmask(SIG_BLOCK, &mask, &omask); 59 | switch (pid = vfork()) { 60 | case -1: /* error */ 61 | sigprocmask(SIG_SETMASK, &omask, NULL); 62 | return(-1); 63 | case 0: /* child */ 64 | sigprocmask(SIG_SETMASK, &omask, NULL); 65 | execve(_PATH_BSHELL, argp, environ); 66 | _exit(127); 67 | } 68 | 69 | intsave = (sig_t) bsd_signal(SIGINT, SIG_IGN); 70 | quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN); 71 | pid = waitpid(pid, (int *)&pstat, 0); 72 | sigprocmask(SIG_SETMASK, &omask, NULL); 73 | (void)bsd_signal(SIGINT, intsave); 74 | (void)bsd_signal(SIGQUIT, quitsave); 75 | return (pid == -1 ? -1 : pstat); 76 | } 77 | --------------------------------------------------------------------------------