A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 168 lines 5.3 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * 9 * Copyright (C) 2013 Lorenzo Miori 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation; either version 2 14 * of the License, or (at your option) any later version. 15 * 16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 17 * KIND, either express or implied. 18 * 19 ****************************************************************************/ 20 21#include <stdio.h> 22#include <string.h> 23#include <stdlib.h> 24#include <stdarg.h> 25#include <getopt.h> 26#include <stdint.h> 27#include <stdbool.h> 28#include "common.h" 29 30static char* output_dir = NULL; 31static FILE* input_file = NULL; 32static struct firmware_data fw; 33 34static void cleanup(void) 35{ 36 for (int i = 0; i < YPR0_COMPONENTS_COUNT; i++) 37 { 38 free(fw.component_data[i]); 39 } 40} 41 42static void die(int error) 43{ 44 if (input_file != NULL) 45 fclose(input_file); 46 free(output_dir); 47 cleanup(); 48 exit(error); 49} 50 51int main(int argc, char **argv) 52{ 53 FILE* component_handle = NULL; 54 FILE* rev_info_file = NULL; 55 char* tmp_path = malloc(MAX_PATH); 56 int error = 0; 57 bool md5sum_error = false; 58 59 memset(&fw, 0, sizeof(fw)); 60 61 if (argc < 2) 62 { 63 printf("Decrypts Samsung YP-R0/YP-R1 ROM file format\n" 64 "Usage: fwdecrypt <ROM file path\n" 65 ); 66 return 1; 67 } 68 69 output_dir = malloc(MAX_PATH); 70 output_dir[0] = '\0'; 71 if (argc > 2) 72 { 73 strcpy(output_dir, argv[2]); 74 } 75 76 /* open the output file for write */ 77 input_file = fopen(argv[1], "rb"); 78 if (input_file == NULL) 79 { 80 fprintf(stderr, "Cannot open file for reading: %m\n"); 81 die(SAMSUNG_READ_ERROR); 82 } 83 84 /* read some generic information */ 85 join_path(tmp_path, output_dir, "RevisionInfo.txt"); 86 rev_info_file = fopen(tmp_path, "w"); 87 for (int i = 0; i < 5; i++) 88 { 89 char info[MAX_HEADER_LEN]; 90 error += fgets(info, MAX_HEADER_LEN, input_file) == NULL; 91 printf("%s", info); 92 if (rev_info_file != NULL) 93 fprintf(rev_info_file, "%s", info); 94 } 95 if (rev_info_file != NULL) 96 fclose(rev_info_file); 97 98 if (error != 0) 99 { 100 fprintf(stderr, "Cannot write generic header\n"); 101 die(SAMSUNG_WRITE_ERROR); 102 } 103 104 /* read metadata */ 105 for (int i = 0; i < YPR0_COMPONENTS_COUNT; i++) 106 { 107 char metadata[MAX_HEADER_LEN]; 108 error += fgets(metadata, MAX_HEADER_LEN, input_file) == NULL; 109 error += sscanf(metadata, "%*s : size(%ld),checksum(%s)", 110 &fw.component_size[i], fw.component_checksum[i]) != 2; 111 /* strip last ")" */ 112 fw.component_checksum[i][strlen(fw.component_checksum[i])-1] = '\0'; 113 printf("%s: %ld bytes -- MD5 %s\n", firmware_components[i], 114 fw.component_size[i], fw.component_checksum[i]); 115 } 116 117 /* We start from the end because ROM header could have a different 118 * line count or extra new-lines (noticed in some hacked ROMs) 119 */ 120 size_t current_pos = get_filesize(input_file); 121 for (int i = YPR0_COMPONENTS_COUNT-1; i >= 0; i--) 122 { 123 124 fw.component_data[i] = malloc(fw.component_size[i]); 125 current_pos -= fw.component_size[i]; 126 fseek(input_file, current_pos, SEEK_SET); 127 size_t bread = fread(fw.component_data[i], 1, fw.component_size[i], input_file); 128 if (bread != fw.component_size[i]) 129 fprintf(stderr, "%s: Read size mismatch: read %ld bytes, expected %ld bytes\n", 130 firmware_components[i], bread, fw.component_size[i]); 131 132 /* decrypt data */ 133 cyclic_xor(fw.component_data[i], fw.component_size[i], g_yp_key, sizeof(g_yp_key)); 134 135 /* unpatch bootloader */ 136 if (strcmp("MBoot", firmware_components[i]) == 0) 137 { 138 memset(fw.component_data[i] + MBOOT_CHECKSUM_OFFSET, 0, MBOOT_CHECKSUM_LENGTH); 139 } 140 141 char md5sum_decrypted[MD5_DIGEST_LENGTH*2+1]; 142 143 md5sum(md5sum_decrypted, fw.component_data[i], fw.component_size[i]); 144 145 if (strcmp(md5sum_decrypted, fw.component_checksum[i]) != 0) 146 { 147 printf("%s: FAIL (md5sum doesn't match)\n", firmware_components[i]); 148 md5sum_error = true; 149 } 150 151 join_path(tmp_path, output_dir, firmware_filenames[i]); 152 component_handle = fopen(tmp_path, "wb"); 153 154 if (component_handle == NULL) 155 { 156 fprintf(stderr, "Error opening file for writing. Is the directory valid and writeable?\n"); 157 die(SAMSUNG_WRITE_ERROR); 158 } 159 160 fwrite(fw.component_data[i], 1, fw.component_size[i], component_handle); 161 fclose(component_handle); 162 163 } 164 165 if (md5sum_error) 166 die(SAMSUNG_MD5_ERROR); 167 die(SAMSUNG_SUCCESS); 168}