A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
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 "common.h"
28
29static char* input_dir = NULL;
30static FILE* output_file = NULL;
31static struct firmware_data fw;
32
33static void cleanup(void)
34{
35 for (int i = 0; i < YPR0_COMPONENTS_COUNT; i++)
36 {
37 free(fw.component_data[i]);
38 }
39}
40
41static void die(int error)
42{
43 if (output_file != NULL)
44 fclose(output_file);
45 free(input_dir);
46 cleanup();
47 exit(error);
48}
49
50static void pad4byte(char byte, FILE* handle) {
51 int padding = 4 - ftell(handle) % 4;
52 if (padding != 4) {
53 while (padding-- > 0) {
54 fwrite(&byte, 1, 1, handle);
55 }
56 }
57}
58
59int main(int argc, char **argv)
60{
61 FILE* component_handle = NULL;
62 FILE* rev_info_file = NULL;
63 int error = 0;
64 char* tmp_path = malloc(MAX_PATH);
65
66 memset(&fw, 0, sizeof(fw));
67
68 if (argc < 2)
69 {
70 printf(
71 "Crypts Samsung YP-R0/YP-R1 ROM file format\n"
72 "Usage: fwcrypt <output ROM file path\n"
73 );
74 return 1;
75 }
76
77 input_dir = malloc(MAX_PATH);
78 input_dir[0] = '\0';
79 if (argc > 2)
80 {
81 strcpy(input_dir, argv[2]);
82 }
83
84 /* open the output file for write */
85 output_file = fopen(argv[1], "wb");
86 if (output_file == NULL)
87 {
88 fprintf(stderr, "Cannot open file for writing: %m\n");
89 die(SAMSUNG_WRITE_ERROR);
90 }
91
92 /* write generic header */
93 join_path(tmp_path, input_dir, "RevisionInfo.txt");
94 rev_info_file = fopen(tmp_path, "rb");
95 if (rev_info_file != NULL)
96 {
97 for (int i = 0; i < GENERIC_HEADER_LINES; i++)
98 {
99 char header[MAX_HEADER_LEN];
100 error += fgets(header, MAX_HEADER_LEN, rev_info_file) == NULL;
101 error += fprintf(output_file, "%s", header) != (signed)strlen(header);
102 }
103 fclose(rev_info_file);
104 }
105 else
106 {
107 /* write some generic information */
108 error += fprintf(output_file, YPR0_VERSION) != strlen(YPR0_VERSION);
109 error += fprintf(output_file, YPR0_TARGET) != strlen(YPR0_TARGET);
110 error += fprintf(output_file, YPR0_USER) != strlen(YPR0_USER);
111 error += fprintf(output_file, YPR0_DIR) != strlen(YPR0_DIR);
112 error += fprintf(output_file, YPR0_TIME) != strlen(YPR0_TIME);
113 }
114
115 if(error != 0)
116 {
117 fprintf(stderr, "Cannot write generic header\n");
118 die(SAMSUNG_WRITE_ERROR);
119 }
120
121 for (int i = 0; i < YPR0_COMPONENTS_COUNT; i++)
122 {
123 join_path(tmp_path, input_dir, firmware_filenames[i]);
124 component_handle = fopen(tmp_path, "rb");
125 if (component_handle == NULL)
126 {
127 fprintf(stderr, "Error while reading firmware component.\n");
128 die(SAMSUNG_READ_ERROR);
129 }
130 fw.component_size[i] = get_filesize(component_handle);
131 fw.component_data[i] = malloc(fw.component_size[i] * sizeof(char));
132 fread(fw.component_data[i], sizeof(char), fw.component_size[i], component_handle);
133 fclose(component_handle);
134
135 /* compute checksum */
136 md5sum(fw.component_checksum[i], fw.component_data[i], fw.component_size[i]);
137 printf("%s : size(%ld),checksum(%s)\n", firmware_components[i],
138 fw.component_size[i], fw.component_checksum[i]);
139 /* write metadata header to file */
140 if (fprintf(output_file, "%s : size(%ld),checksum(%s)\n", firmware_components[i],
141 fw.component_size[i], fw.component_checksum[i]) < 0)
142 {
143 fprintf(stderr, "Error writing to output file.\n");
144 die(SAMSUNG_WRITE_ERROR);
145 }
146 }
147
148 /* Padding */
149 pad4byte('\n', output_file);
150
151 /* write final data to the firmware file */
152 for (int i = 0; i < YPR0_COMPONENTS_COUNT; i++)
153 {
154 /* the bootloader needs to be patched: add checksum of the components */
155 if (strcmp("MBoot", firmware_components[i]) == 0)
156 {
157 int index=MBOOT_CHECKSUM_OFFSET;
158 for (int z = 0; z < YPR0_COMPONENTS_COUNT; z++)
159 {
160 index += sprintf(fw.component_data[i] + index, "%ld:%s\n",
161 fw.component_size[z], fw.component_checksum[z]);
162 }
163 }
164 /* crypt data */
165 cyclic_xor(fw.component_data[i], fw.component_size[i], g_yp_key, sizeof(g_yp_key));
166 /* write data */
167 size_t written = fwrite(fw.component_data[i], sizeof(char),
168 fw.component_size[i], output_file);
169 if (written != fw.component_size[i])
170 {
171 fprintf(stderr, "%s: error writing data to file. Written %ld bytes\n",
172 firmware_components[i], written);
173 die(SAMSUNG_WRITE_ERROR);
174 }
175 /* padding */
176 if (i < (YPR0_COMPONENTS_COUNT-1))
177 pad4byte('\0', output_file);
178 }
179
180 /* free the big amount of memory and close handles */
181 die(SAMSUNG_SUCCESS);
182}