logo

live-bootstrap

Mirror of <https://github.com/fosslinux/live-bootstrap>

make_fiwix_initrd.c (8452B)


  1. /*
  2. * SPDX-FileCopyrightText: Copyright (c) 2015 Grzegorz Kostka (kostka.grzegorz@gmail.com)
  3. * SPDX-License-Identifier: BSD-3-Clause
  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. *
  10. * - Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * - Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * - The name of the author may not be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  19. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  20. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. * Modifications:
  30. * SPDX-FileCopyrightText: 2023 Richard Masters <grick23@gmail.com>
  31. * SPDX-License-Identifier: MIT
  32. */
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <unistd.h>
  37. #include <stdbool.h>
  38. #include <inttypes.h>
  39. #include <time.h>
  40. #include <unistd.h>
  41. #include <sys/time.h>
  42. #include <ext4.h>
  43. #include <ext4_mkfs.h>
  44. #include "../blockdev/linux/file_dev.h"
  45. #include "../blockdev/windows/file_windows.h"
  46. #define BLOCK_SIZE 1024
  47. #define FILENAME_LENGTH 1024
  48. const char *input_name = NULL;
  49. /**@brief Block device handle.*/
  50. static struct ext4_blockdev *bd;
  51. /**@brief Block cache handle.*/
  52. static struct ext4_bcache *bc;
  53. static struct ext4_fs fs;
  54. static struct ext4_mkfs_info info = {
  55. .block_size = BLOCK_SIZE,
  56. .journal = false,
  57. .inode_size = 128,
  58. };
  59. #define MKDEV(major, minor) (((major) << 8) | (minor))
  60. static bool open_filedev(void)
  61. {
  62. file_dev_name_set(input_name);
  63. bd = file_dev_get();
  64. if (!bd) {
  65. puts("open_filedev: fail");
  66. return false;
  67. }
  68. return true;
  69. }
  70. bool lwext4_mount(struct ext4_blockdev *bdev, struct ext4_bcache *bcache)
  71. {
  72. int r;
  73. bc = bcache;
  74. bd = bdev;
  75. if (!bd) {
  76. puts("lwext4_mount: no block device");
  77. return false;
  78. }
  79. /* ext4_dmask_set(DEBUG_ALL); */
  80. r = ext4_device_register(bd, "ext4_fs");
  81. if (r != EOK) {
  82. printf("ext4_device_register: rc = %d\n", r);
  83. return false;
  84. }
  85. r = ext4_mount("ext4_fs", "/mp/", false);
  86. if (r != EOK) {
  87. printf("ext4_mount: rc = %d\n", r);
  88. return false;
  89. }
  90. r = ext4_recover("/mp/");
  91. if (r != EOK && r != ENOTSUP) {
  92. printf("ext4_recover: rc = %d\n", r);
  93. return false;
  94. }
  95. /* ext4_cache_write_back("/mp/", 1); */
  96. return true;
  97. }
  98. bool lwext4_umount(void)
  99. {
  100. int r;
  101. /* ext4_cache_write_back("/mp/", 0); */
  102. r = ext4_umount("/mp/");
  103. if (r != EOK) {
  104. printf("ext4_umount: fail %d", r);
  105. return false;
  106. }
  107. return true;
  108. }
  109. bool copy_file(char *src_path, char *dest_path)
  110. {
  111. ext4_file dest_file;
  112. int err;
  113. err = ext4_inode_exist(dest_path, EXT4_DE_UNKNOWN);
  114. if (err == EOK) {
  115. /* file already copied or directory already created */
  116. return EXIT_SUCCESS;
  117. }
  118. printf("copy_file: %s\n", src_path);
  119. FILE *src_file = fopen(src_path, "rb");
  120. if (!src_file) {
  121. printf("fopen '%s' error.\n", src_path);
  122. return EXIT_FAILURE;
  123. }
  124. fseek(src_file, 0, SEEK_END);
  125. int src_len = ftell(src_file);
  126. fseek(src_file, 0, SEEK_SET);
  127. char * src_mem = malloc(src_len);
  128. int read_len = fread(src_mem, src_len, 1, src_file);
  129. fclose(src_file);
  130. if (read_len < 1) {
  131. printf("src fread error file: '%s' read count: %d\n", src_path, read_len);
  132. }
  133. err = ext4_fopen(&dest_file, dest_path, "wb");
  134. if (err != EOK) {
  135. printf("ext4_open error: %d\n", err);
  136. return EXIT_FAILURE;
  137. }
  138. if (src_len > 0) {
  139. err = ext4_fwrite(&dest_file, src_mem, src_len, 0);
  140. if (err != EOK) {
  141. printf("ext4_fwrite error: %d\n", err);
  142. return EXIT_FAILURE;
  143. }
  144. }
  145. err = ext4_fclose(&dest_file);
  146. if (err != EOK) {
  147. printf("ext4_fclose error: %d\n", err);
  148. return EXIT_FAILURE;
  149. }
  150. free(src_mem);
  151. }
  152. bool copy_file_system()
  153. {
  154. int filenum;
  155. unsigned int filename_addr;
  156. /* +4 to account for /mp and null termination */
  157. char dst_filename[FILENAME_LENGTH + 4];
  158. for (filenum = 14335, filename_addr = 0xfffc00; filenum >= 3; filenum--, filename_addr -= FILENAME_LENGTH) {
  159. /* Avoid including fiwix.ext2 in itself */
  160. if (((char *) filename_addr)[0] != '/' ||
  161. !strcmp((char *) filename_addr, "/") ||
  162. !strcmp((char *) filename_addr, "/boot/fiwix.ext2")) {
  163. continue;
  164. }
  165. strcpy(dst_filename, "/mp");
  166. strcat(dst_filename, (char *) filename_addr);
  167. copy_file((char *) filename_addr, dst_filename);
  168. }
  169. }
  170. int main(int argc, char **argv)
  171. {
  172. int err;
  173. char zeros[BLOCK_SIZE];
  174. unsigned int next_file_address;
  175. int filenum;
  176. unsigned int filename_addr;
  177. unsigned int file_addr;
  178. unsigned int initrd_size;
  179. int i;
  180. next_file_address = 0x54000000;
  181. for (filenum = 14335, filename_addr = 0xfffc00, file_addr = 0x1037FF4;
  182. filenum >= 3;
  183. filenum--, filename_addr -= FILENAME_LENGTH, file_addr -= 16) {
  184. if (((char *) filename_addr)[0] == '/') {
  185. next_file_address = *((unsigned int *) file_addr);
  186. next_file_address += *((unsigned int *) (file_addr + 4));
  187. break;
  188. }
  189. }
  190. /* Create zeroed out disk image file */
  191. input_name = "/boot/fiwix.ext2";
  192. initrd_size = 262144;
  193. for (i = 1; i < argc; i++) {
  194. if (!strcmp(argv[i], "-s")) {
  195. i++;
  196. initrd_size = atoi(argv[i]);
  197. } else {
  198. input_name = argv[i];
  199. }
  200. }
  201. printf("Starting %s at addr 0x%08x\n", input_name, next_file_address);
  202. memset(zeros, 0, BLOCK_SIZE);
  203. FILE *ext2file = fopen(input_name, "w");
  204. int b;
  205. for (b=0; b < initrd_size; b++)
  206. fwrite(zeros, BLOCK_SIZE, 1, ext2file);
  207. fclose(ext2file);
  208. if (!open_filedev()) {
  209. printf("open_filedev error\n");
  210. return EXIT_FAILURE;
  211. }
  212. /* ext4_dmask_set(DEBUG_ALL); */
  213. err = ext4_mkfs(&fs, bd, &info, F_SET_EXT2_V0);
  214. if (err != EOK) {
  215. printf("ext4_mkfs error: %d\n", err);
  216. return EXIT_FAILURE;
  217. }
  218. memset(&info, 0, sizeof(struct ext4_mkfs_info));
  219. err = ext4_mkfs_read_info(bd, &info);
  220. if (err != EOK) {
  221. printf("ext4_mkfs_read_info error: %d\n", err);
  222. return EXIT_FAILURE;
  223. }
  224. printf("Created filesystem with parameters:\n");
  225. printf("Size: %"PRIu64"\n", info.len);
  226. printf("Block size: %"PRIu32"\n", info.block_size);
  227. printf("Blocks per group: %"PRIu32"\n", info.blocks_per_group);
  228. printf("Inodes per group: %"PRIu32"\n", info.inodes_per_group);
  229. printf("Inode size: %"PRIu32"\n", info.inode_size);
  230. printf("Inodes: %"PRIu32"\n", info.inodes);
  231. printf("Journal blocks: %"PRIu32"\n", info.journal_blocks);
  232. printf("Features ro_compat: 0x%x\n", info.feat_ro_compat);
  233. printf("Features compat: 0x%x\n", info.feat_compat);
  234. printf("Features incompat: 0x%x\n", info.feat_incompat);
  235. printf("BG desc reserve: %"PRIu32"\n", info.bg_desc_reserve_blocks);
  236. printf("Descriptor size: %"PRIu32"\n",info.dsc_size);
  237. printf("Label: %s\n", info.label);
  238. if (!lwext4_mount(bd, bc))
  239. return EXIT_FAILURE;
  240. puts("ext4_dir_mk /mp/dev");
  241. err = ext4_dir_mk("/mp/dev");
  242. if (err != EOK) {
  243. printf("ext4_dir_mk error: %d\n", err);
  244. }
  245. puts("ext4_dir_mk /mp/tmp");
  246. err = ext4_dir_mk("/mp/tmp");
  247. if (err != EOK) {
  248. printf("ext4_dir_mk error: %d\n", err);
  249. }
  250. puts("ext4_mknod /mp/dev/console");
  251. err = ext4_mknod("/mp/dev/console", EXT4_DE_CHRDEV, MKDEV(5, 1));
  252. if (err != EOK) {
  253. printf("ext4_mknod error: %d\n", err);
  254. return EXIT_FAILURE;
  255. }
  256. puts("ext4_mknod /mp/dev/ram0");
  257. err = ext4_mknod("/mp/dev/ram0", EXT4_DE_BLKDEV, MKDEV(1, 0));
  258. if (err != EOK) {
  259. printf("ext4_mknod error: %d\n", err);
  260. return EXIT_FAILURE;
  261. }
  262. puts("ext4_mknod /mp/dev/ram1");
  263. err = ext4_mknod("/mp/dev/ram1", EXT4_DE_BLKDEV, MKDEV(1, 1));
  264. if (err != EOK) {
  265. printf("ext4_mknod error: %d\n", err);
  266. return EXIT_FAILURE;
  267. }
  268. copy_file_system();
  269. if (!lwext4_umount())
  270. return EXIT_FAILURE;
  271. puts("Fiwix ext2 initrd created successfully.");
  272. return EXIT_SUCCESS;
  273. }