Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
sdcontent.c
Go to the documentation of this file.
1 /* A work-in-progess MEGA65 (Commodore 65 clone origins) emulator
2  Part of the Xemu project, please visit: https://github.com/lgblgblgb/xemu
3  Copyright (C)2016-2022 LGB (Gábor Lénárt) <lgblgblgb@gmail.com>
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18 
19 #ifdef SD_CONTENT_SUPPORT
20 
21 #include "xemu/emutools.h"
22 #include "sdcontent.h"
23 #include "sdcard.h"
24 #include "fat32.h"
25 #include "mega65.h"
26 #include "xemu/d81access.h"
27 #include "xemu/emutools_files.h"
28 #include "rom.h"
29 
30 #include "memcontent.h"
31 
32 #include <string.h>
33 #include <sys/types.h>
34 #include <dirent.h>
35 #include <errno.h>
36 #include <sys/stat.h>
37 #include <unistd.h>
38 
39 #define MAX_IMPORT_FILE_SIZE 1000000
40 
41 
42 
43 static Uint8 block[512];
44 static int our_data_partition;
45 
46 static mfat_dirent_t sd_rootdirent;
47 
48 
49 // From mega65-fdisk
50 static const Uint8 fat_bytes[12] = {
51  0xf8,0xff,0xff,0x0f,
52  0xff,0xff,0xff,0x0f,
53  0xf8,0xff,0xff,0x0f
54 };
55 static const Uint8 dir_bytes[15] = {0x08,0x00,0x00,0x53,0xae,0x93,0x4a,0x93,0x4a,0x00,0x00,0x53,0xae,0x93,0x4a};
56 static const Uint8 default_volume_name[11] = "M.E.G.A.65!";
57 static const char default_disk_image[] = "mega65.d81"; // must be lower case
58 static const char xemu_disk_image[] = "external.d81";
59 static const Uint8 sys_part_magic[] = {'M','E','G','A','6','5','S','Y','S','0','0'};
60 static const Uint8 boot_bytes[258] = {
61  // Jump to boot code, required by most version of DOS
62  0xeb, 0x58, 0x90,
63  // OEM String: MEGA65r1
64  0x4d, 0x45, 0x47, 0x41, 0x36, 0x35, 0x72, 0x31,
65  // BIOS Parameter block. We patch certain
66  // values in here.
67  0x00, 0x02, // Sector size = 512 bytes
68  0x08 , // Sectors per cluster
69  /* 0x0e */ 0x38, 0x02, // Number of reserved sectors (0x238 = 568)
70  /* 0x10 */ 0x02, // Number of FATs
71  0x00, 0x00, // Max directory entries for FAT12/16 (0 for FAT32)
72  /* offset 0x13 */ 0x00, 0x00, // Total logical sectors (0 for FAT32)
73  0xf8, // Disk type (0xF8 = hard disk)
74  0x00, 0x00, // Sectors per FAT for FAT12/16 (0 for FAT32)
75  /* offset 0x18 */ 0x00, 0x00, // Sectors per track (0 for LBA only)
76  0x00, 0x00, // Number of heads for CHS drives, zero for LBA
77  0x00, 0x00, 0x00, 0x00, // 32-bit Number of hidden sectors before partition. Should be 0 if logical sectors == 0
78  /* 0x20 */ 0x00, 0xe8, 0x0f, 0x00, // 32-bit total logical sectors
79  /* 0x24 */ 0xf8, 0x03, 0x00, 0x00, // Sectors per FAT
80  /* 0x28 */ 0x00, 0x00, // Drive description
81  /* 0x2a */ 0x00, 0x00, // Version 0.0
82  /* 0x2c */ 0x02, 0x00 ,0x00, 0x00, // Number of first cluster
83  /* 0x30 */ 0x01, 0x00, // Logical sector of FS Information sector
84  /* 0x32 */ 0x06, 0x00, // Sector number of backup-copy of boot sector
85  /* 0x34 */ 0x00, 0x00, 0x00, 0x00, // Filler bytes
86  0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,0x00, 0x00, // Filler bytes
87  /* 0x40 */ 0x80, // Physical drive number
88  /* 0x41 */ 0x00, // FAT12/16 use only
89  /* 0x42 */ 0x29, // 0x29 == Extended Boot Signature
90  /* 0x43 */ 0x6d, 0x66, 0x62, 0x61, // Volume ID "mfba"
91  /* 0x47 */ 0x4d, 0x2e, 0x45, 0x2e, 0x47, // 11 byte volume label
92  0x2e, 0x41 ,0x2e, 0x20, 0x36, 0x35,
93  /* 0x52 */ 0x46, 0x41, 0x54, 0x33, 0x32, 0x20, 0x20, 0x20, // "FAT32 "
94  // Boot loader code starts here
95  0x0e, 0x1f, 0xbe, 0x77 ,0x7c, 0xac,
96  0x22, 0xc0, 0x74, 0x0b, 0x56, 0xb4, 0x0e, 0xbb,
97  0x07, 0x00, 0xcd, 0x10, 0x5e, 0xeb ,0xf0, 0x32,
98  0xe4, 0xcd, 0x16, 0xcd, 0x19, 0xeb, 0xfe,
99  // From here on is the non-bootable error message
100  // 0x82 - 0x69 =
101  0x4d, 0x45, 0x47, 0x41, 0x36, 0x35, 0x20,
102  // 9-character name of operating system
103  'H','Y','P','P','O','B','O','O','T',
104  0x20, 0x56, 0x30, 0x30, 0x2e, 0x31, 0x31,
105  0x0d, 0x0a, 0x0d, 0x3f, 0x4e, 0x4f, 0x20, 0x34,
106  0x35, 0x47, 0x53, 0x30, 0x32, 0x2c, 0x20, 0x34,
107  0x35, 0x31, 0x30, 0x2c, 0x20, 0x36, 0x35, 0x5b,
108  0x63, 0x65, 0x5d, 0x30, 0x32, 0x2c, 0x20, 0x36,
109  0x35, 0x31, 0x30, 0x20, 0x4f, 0x52, 0x20, 0x38,
110  0x35, 0x31, 0x30, 0x20, 0x50, 0x52, 0x4f, 0x43,
111  0x45, 0x53, 0x53, 0x4f, 0x52, 0x20, 0x20, 0x45,
112  0x52, 0x52, 0x4f, 0x52, 0x0d, 0x0a, 0x49, 0x4e, 0x53,
113  0x45, 0x52, 0x54, 0x20, 0x44, 0x49, 0x53, 0x4b,
114  0x20, 0x49, 0x4e, 0x20, 0x52, 0x45, 0x41, 0x4c,
115  0x20, 0x43, 0x4f, 0x4d, 0x50, 0x55, 0x54, 0x45,
116  0x52, 0x20, 0x41, 0x4e, 0x44, 0x20, 0x54, 0x52,
117  0x59, 0x20, 0x41, 0x47, 0x41, 0x49, 0x4e, 0x2e,
118  0x0a, 0x0a, 0x52, 0x45, 0x41, 0x44, 0x59, 0x2e,
119  0x0d, 0x0a
120 };
121 
122 #define ZERO_BUFFER() memset(block,0,512)
123 #define WRITE_BLOCK(n) do { if (sdcard_write_block(n,block)) return -1; } while(0)
124 #define WRITE_BLOCK_RANGE(n1,n2) do { for (Uint32 i = n1; i <= n2; i++) if (sdcard_write_block(i,block)) return -1; } while(0)
125 
126 static inline void block_uint32 ( unsigned int ofs, Uint32 data )
127 {
128  block[ofs ] = (data ) & 0xff;
129  block[ofs + 1] = (data >> 8) & 0xff;
130  block[ofs + 2] = (data >> 16) & 0xff;
131  block[ofs + 3] = (data >> 24) & 0xff;
132 }
133 static inline void block_uint16 ( unsigned int ofs, Uint16 data )
134 {
135  block[ofs ] = (data ) & 0xff;
136  block[ofs + 1] = (data >> 8) & 0xff;
137 }
138 
139 
140 // Make a FAT32FS. Called by fdisk() function
141 // I copied the algorithm from mega65-fdisk closely (and hopefully well enough) not to have any compatibility issue.
142 static int mkfs_fat32 ( Uint32 start_block, Uint32 number_of_blocks )
143 {
144  DEBUGPRINT("SDCARD: FAT32FS: creating file system between sectors $%X-$%X, $%X sectors (%uK) in size" NL, start_block, start_block + number_of_blocks - 1, number_of_blocks, number_of_blocks >> 11);
145  // *** Let's do some calculations. According to mega65-fdisk, as usual in these mkfs parts :)
146  const Uint8 sectors_per_cluster = 8; // 4Kbyte clusters
147  //Uint32 reserved_sectors = 1024 * 1024 / 512;
148  const Uint32 reserved_sectors = boot_bytes[0xE] + (boot_bytes[0xF] << 8);
149  const Uint32 fat_available_sectors = number_of_blocks - reserved_sectors;
150  Uint32 fs_clusters = fat_available_sectors / sectors_per_cluster;
151  Uint32 fat_sectors = fs_clusters/(512 / 4);
152  if (fs_clusters % (512 / 4))
153  fat_sectors++;
154  Uint32 sectors_required = 2 * fat_sectors+((fs_clusters - 2) * sectors_per_cluster);
155  while (sectors_required > fat_available_sectors) {
156  Uint32 excess_sectors = sectors_required - fat_available_sectors;
157  Uint32 delta = (excess_sectors / (1 + sectors_per_cluster));
158  if (delta < 1)
159  delta = 1;
160  fs_clusters -= delta;
161  fat_sectors = fs_clusters / (512 / 4);
162  if (fs_clusters % (512 / 4))
163  fat_sectors++;
164  sectors_required = 2 * fat_sectors + ((fs_clusters - 2) * sectors_per_cluster);
165  }
166  Uint32 fat1_sector = reserved_sectors;
167  Uint32 fat2_sector = fat1_sector + fat_sectors;
168  Uint32 rootdir_sector = fat2_sector + fat_sectors;
169  // *** Create boot sector
170  ZERO_BUFFER();
171  memcpy(block, boot_bytes, sizeof boot_bytes);
172  // 0x20-0x23 = 32-bit number of data sectors in file system
173  //for (int i = 0; i < 4; i++)
174  // block[0x20 + i] = (number_of_blocks >> (i * 8)) & 0xff;
175  block_uint32(0x20, number_of_blocks);
176  // 0x24-0x27 = 32-bit number of sectors per fat
177  //for (int i = 0; i < 4; i++)
178  // block[0x24 + i] = (fat_sectors >> (i * 8)) & 0xff;
179  block_uint32(0x24, fat_sectors);
180  //block_uint16(0x0e, reserved_sectors);
181  block[510] = 0x55; // boot signature
182  block[511] = 0xaa; // boot signature
183  WRITE_BLOCK(start_block); // write boot sector
184  WRITE_BLOCK(start_block + 6); // write backup boot sector (the very same, with @ +6 sector)
185  // *** Create FAT FS information sector
186  ZERO_BUFFER();
187  block[0] = 0x52; // four "magic" bytes
188  block[1] = 0x52;
189  block[2] = 0x61;
190  block[3] = 0x41;
191  block[0x1e4] = 0x72; // four another "mgic" bytes
192  block[0x1e5] = 0x72;
193  block[0x1e6] = 0x41;
194  block[0x1e7] = 0x61;
195  //for(int i = 0; i < 4; i++) // Number of free clusters
196  // block[0x1e8 + i] = ((fs_clusters - 3) >> (i * 8)) & 0xff;
197  //block_uint32(0x1e8, fs_clusters - 3);
198  block_uint32(0x1e8, 0xFFFFFFFFU); // according to some documents, this must be set to FFFFFFFF if not used
199  // First free cluster = 2
200  //block[0x1ec] = 0x02 + 1; // OSX newfs/fsck puts 3 here instead?
201  block_uint32(0x1ec, 0xFFFFFFFFU); // according to some documents, this must be set to FFFFFFFF if not used
202  // Boot sector signature
203  block[510] = 0x55;
204  block[511] = 0xaa;
205  WRITE_BLOCK(start_block + 1);
206  WRITE_BLOCK(start_block + 7);
207  // *** Build empty FATs
208  ZERO_BUFFER();
209  memcpy(block, fat_bytes, sizeof fat_bytes);
210  WRITE_BLOCK(start_block + fat1_sector);
211  WRITE_BLOCK(start_block + fat2_sector);
212  // *** Build empty root directory
213  ZERO_BUFFER();
214  memcpy(block, default_volume_name, 11);
215  memcpy(block + 11, dir_bytes, sizeof dir_bytes);
216  WRITE_BLOCK(start_block + rootdir_sector);
217  // *** Erase some sectors
218  ZERO_BUFFER();
219  WRITE_BLOCK_RANGE(start_block + 1 + 1, start_block + 6 - 1);
220  WRITE_BLOCK_RANGE(start_block + 6 + 1, start_block + fat1_sector - 1);
221  WRITE_BLOCK_RANGE(start_block + fat1_sector + 1, start_block + fat2_sector - 1);
222  WRITE_BLOCK_RANGE(start_block + fat2_sector + 1, start_block + rootdir_sector - 1);
223  WRITE_BLOCK_RANGE(start_block + rootdir_sector + 1, start_block + rootdir_sector + 1 + sectors_per_cluster - 1);
224  return 0;
225 }
226 
227 
228 
229 static int mksyspart ( Uint32 start_block, Uint32 number_of_blocks )
230 {
231  Uint32 slot_size = 512 * 1024 / 512; // slot_size units is sectors
232  // Take 1MB from partition size, for reserved space when
233  // calculating what can fit.
234  Uint32 reserved_sectors = 1024 * 1024 / 512;
235  Uint32 slot_count = (number_of_blocks - reserved_sectors) / (slot_size * 2 + 1);
236  if (slot_count >= 0xffff)
237  slot_count = 0xffff;
238  Uint16 dir_size = 1 + (slot_count / 4);
239  Uint16 freeze_dir_sectors = dir_size;
240  Uint16 service_dir_sectors = dir_size;
241  // Freeze directory begins at 1MB
242  Uint32 sys_partition_freeze_dir = reserved_sectors;
243  // System service directory begins after that
244  Uint32 sys_partition_service_dir = sys_partition_freeze_dir + slot_size * slot_count;
245  // *** System sector
246  ZERO_BUFFER();
247  memcpy(block, sys_part_magic, sizeof sys_part_magic); // magic bytes
248  block_uint32(0x10, 0); // $010-$013 = Start of freeze program area
249  block_uint32(0x14, slot_size * slot_count + dir_size); // $014-$017 = Size of freeze program area
250  block_uint32(0x18, slot_size); // $018-$01b = Size of each freeze program slot
251  block_uint16(0x1c, slot_count); // $01c-$01d = Number of freeze slots
252  block_uint16(0x1e, dir_size); // $01e-$01f = Number of sectors in freeze slot directory
253  block_uint32(0x20, slot_size * slot_count + dir_size); // $020-$023 = Start of freeze program area
254  block_uint32(0x24, slot_size * slot_count + dir_size); // $024-$027 = Size of service program area
255  block_uint32(0x28, slot_size); // $028-$02b = Size of each service slot
256  block_uint16(0x2c, slot_count); // $02c-$02d = Number of service slots
257  block_uint16(0x2e, dir_size); // $02e-$02f = Number of sectors in service slot directory
258  // Now make sector numbers relative to start of disk for later use
259  sys_partition_freeze_dir += start_block;
260  sys_partition_service_dir += start_block;
261  WRITE_BLOCK(start_block);
262  // *** Config sector
263  ZERO_BUFFER();
264  block[0x000] = 0x01; // Structure version bytes
265  block[0x001] = 0x01;
266  block[0x002] = 0x80; // PAL=$00, NTSC=$80
267  block[0x003] = 0x41; // Enable audio amp, mono output
268  block[0x004] = 0x00; // Use SD card for floppies
269  block[0x005] = 0x01; // Enable use of Amiga mouses automatically
270  block[0x006] = 0x41; // Ethenet MAC, start, from mega65-fdisk: "Should do a better job of this!"
271  block[0x007] = 0x41;
272  block[0x008] = 0x41;
273  block[0x009] = 0x41;
274  block[0x00A] = 0x41;
275  block[0x00B] = 0x41; // Ethernet MAC, end
276  // Set name of default disk image
277  memcpy(block + 0x10, default_disk_image, strlen(default_disk_image));
278  // DMAgic version: default, new revision (F011B)
279  block[0x020]=0x01;
280  WRITE_BLOCK(start_block + 1U);
281  // ***** erase some sectors
282  ZERO_BUFFER();
283  // Erase the rest of the 1MB reserved area
284  WRITE_BLOCK_RANGE(start_block + 2, start_block + 1023);
285  // erase frozen program directory
286  WRITE_BLOCK_RANGE(sys_partition_freeze_dir, sys_partition_freeze_dir + freeze_dir_sectors - 1);
287  // erase system service image directory
288  WRITE_BLOCK_RANGE(sys_partition_service_dir, sys_partition_service_dir + service_dir_sectors - 1);
289  return 0;
290 }
291 
292 
293 
294 // "fdisk" (ie, partitioning and "format" - make FAT32FS's) the SD-card
295 // Actually this only makes the MBR and partition boundaries, and calls mkfs_fat32() for the filesystem creation on a partition.
296 // I copied the algorithm from mega65-fdisk closely (and hopefully well enough) not to have any compatibility issue.
297 static int fdisk ( Uint32 device_size )
298 {
299  our_data_partition = -1;
300  DEBUGPRINT("SDCARD: FDISK: creating partition table ..." NL);
301  // *** Current policy to create sizes and boundaries of the partitions are based on mega65-fdisk source
302  Uint32 sys_part_sects = (device_size - 0x0800) >> 1;
303  if (sys_part_sects > 0x400000)
304  sys_part_sects = 0x400000;
305  sys_part_sects &= 0xfffff800; // round down to nearest 1MB boundary
306  Uint32 usr_part_sects = device_size - 0x0800 - sys_part_sects;
307  Uint32 usr_part_start = 0x0800;
308  Uint32 sys_part_start = usr_part_start + usr_part_sects;
309  // *** Create partition table (according to mega65-fdisk source itself)
310  // note: zero values are not set to zero individually, as those are the default after ZERO_BUFFER()
311  ZERO_BUFFER();
312  // disk signature, fixed value
313  block[0x1b8] = 0x83;
314  block[0x1b9] = 0x7d;
315  block[0x1ba] = 0xcb;
316  block[0x1bb] = 0xa6;
317  // MBR signature
318  block[0x1fe] = 0x55;
319  block[0x1ff] = 0xaa;
320  // FAT32 data ("user" partition)
321  block[0x1c2] = 0x0c; // partition type, VFAT32
322  block[0x1c6] = (usr_part_start ) & 0xff;
323  block[0x1c7] = (usr_part_start >> 8) & 0xff; // LBA start of our FS
324  block[0x1c8] = (usr_part_start >> 16) & 0xff;
325  block[0x1c9] = (usr_part_start >> 24) & 0xff;
326  block[0x1ca] = (usr_part_sects ) & 0xff; // LBA size of our FS
327  block[0x1cb] = (usr_part_sects >> 8) & 0xff;
328  block[0x1cc] = (usr_part_sects >> 16) & 0xff;
329  block[0x1cd] = (usr_part_sects >> 24) & 0xff;
330  // The 'system' area/partition
331  block[0x1d2] = 0x41; // partition type, MEGA65 system partition
332  block[0x1d6] = (sys_part_start ) & 0xff; // LBA start of our sys-area
333  block[0x1d7] = (sys_part_start >> 8) & 0xff;
334  block[0x1d8] = (sys_part_start >> 16) & 0xff;
335  block[0x1d9] = (sys_part_start >> 24) & 0xff;
336  block[0x1da] = (sys_part_sects ) & 0xff; // LBA size of our sys-area
337  block[0x1db] = (sys_part_sects >> 8) & 0xff;
338  block[0x1dc] = (sys_part_sects >> 16) & 0xff;
339  block[0x1dd] = (sys_part_sects >> 24) & 0xff;
340  WRITE_BLOCK(0);
341  // *** Create FAT32 (data/user area)
342  if (mkfs_fat32(usr_part_start, usr_part_sects))
343  return -1;
344  // *** Create SYSTEM (system area/partition)
345  if (mksyspart(sys_part_start, sys_part_sects))
346  return -1;
347  // *** Make fat32.c to re-read partition table ...
348  DEBUGPRINT("SDCARD: FDISK: Re-reading MBR ..." NL);
349  // this should give result '0' (the 0'th aka first partition is valid)
350  // Note: in this implementation we ALWAYS make data partition as the first one (well, the zero'th ...)
351  if (mfat_init_mbr() != 0)
352  FATAL("First partition entry is not valid even after FDISK!");
353  if (mfat_use_part(0) != 0)
354  FATAL("First partition cannot be used as FAT32FS even after FDISK/MKFS!");
355  our_data_partition = 0;
356  return 0;
357 }
358 
359 /* Parameters:
360  on_card_name: file of the name on the card, will be "DOS-ized", ie 8+3 chars, all capitals. Cannot have directory component!
361  options: options with SDCONTENT_* stuff, to check overwrite is OK, should ask, etc
362  fn_or_data: # if size_to_install > 0, it's a memory pointer, with size_to_install bytes to install from there
363  # if size_to_install = 0, it's a file name to load data from and install that, with the size of the given file
364  # if size_to_install < 0, it's a file name, with -size_to_install long, and size mismatch will be checked and even asserted
365  size_to_install: see above
366  Notes:
367  Currently policy: if file already existed on the image, we will reuse the FAT chain, _IF_ it's not fragmented and would fit.
368  If the FAT chain is not long enough (ie, the size of the new file wouldn't fit in terms of number of clusters) we rather
369  create a NEW fat chain, and free old one. This is because it's easier to do so, and some MEGA65 features (disk images) needs
370  strictly UNFRAGMENTED state anyway.
371 */
372 static int update_sdcard_file ( const char *on_card_name, int options, const char *fn_or_data, int size_to_install )
373 {
374  int fd = -1;
375  DEBUGPRINT("SDCONTENT: about to updating file %s ..." NL, on_card_name);
376  if (size_to_install <= 0) {
377  fd = open(fn_or_data, O_RDONLY | O_BINARY);
378  if (fd < 0) {
379  ERROR_WINDOW("SD-card image updater cannot open file:\n%s\n(%s)", fn_or_data, strerror(errno));
380  goto error_on_maybe_sys_file;
381  }
382  off_t oft = xemu_safe_file_size_by_fd(fd);
383  if (oft == OFF_T_ERROR || (size_to_install < 0 && oft != (off_t)(-size_to_install))) {
384  DEBUGPRINT("Got size: " PRINTF_LLD " instruct size: %d" NL, (long long int)oft, size_to_install);
385  ERROR_WINDOW("Bad file, size is incorrect or other I/O error\n%s", fn_or_data);
386  goto error_on_maybe_sys_file;
387  }
388  size_to_install = (int)oft;
389  if (!size_to_install)
390  return 0; // FIXME: we don't allow empty files to be written. Though we fake OK result no to disturb the user
391  }
392  //mfat_dirent_t rootdir;
393  //mfat_open_rootdir(&rootdir.stream);
394  Uint32 block = mfat_overwrite_file_with_direct_linear_device_block_write(&sd_rootdirent, on_card_name, size_to_install);
395  if (block == 0)
396  goto error_on_maybe_sys_file;
397  // Copy file block by block
398  while (size_to_install) {
399  Uint8 buffer[512];
400  int need = (size_to_install < sizeof buffer) ? size_to_install : sizeof buffer;
401  if (need < sizeof(buffer))
402  memset(buffer + need, 0, sizeof(buffer) - need);
403  if (fd >= 0) {
404  // Read from external file
405  int got = xemu_safe_read(fd, buffer, need);
406  if (got < 0)
407  goto error;
408  if (got == 0)
409  goto error;
410  if (got != need)
411  goto error;
412  } else {
413  // Read from memory
414  memcpy(buffer, fn_or_data, need);
415  fn_or_data += need;
416  }
417  // And now WRITE!!!!!
418  sdcard_write_block(block++, buffer); // FIXME: error handling!!!
419  size_to_install -= need;
420  }
421  if (fd >= 0)
422  close(fd);
423  return 0;
424 error_on_maybe_sys_file:
425  if ((options & SDCONTENT_SYS_FILE))
426  ERROR_WINDOW(
427  "This file is a must for Xemu/MEGA65, however it's under\n"
428  "copyright by their respective owners.\n"
429  "It's totally the user's responsibility to get/use/own/handle this file!\n%s",
430  fn_or_data
431  );
432 error:
433  if (fd >= 0)
434  close(fd);
435  return -1;
436 }
437 
438 
439 static int update_from_directory ( const char *dirname, int options )
440 {
441  DIR *dir = opendir(dirname);
442  if (!dir) {
443  ERROR_WINDOW("Cannot update SD image / virtual-disk:\nCannot open specified directory:\n%s\n%s",
444  dirname,
445  strerror(errno)
446  );
447  return errno;
448  }
449  for (;;) {
450  errno = 0;
451  struct dirent *entry = readdir(dir);
452  if (!entry)
453  break;
454  if (entry->d_name[0] == '.')
455  continue;
456  char fn[PATH_MAX];
457  snprintf(fn, sizeof(fn), "%s" DIRSEP_STR "%s", dirname, entry->d_name);
458  struct stat st;
459  if (stat(fn, &st)) {
460  DEBUGPRINT("SDCARD: CONTENT: skipping updating file \"%s\": start() did not worked: %s" NL, fn, strerror(errno));
461  continue;
462  }
463  if ((st.st_mode & S_IFMT) != S_IFREG) {
464  DEBUGPRINT("SDCARD: CONTENT: skipping updating file \"%s\": not a regular file" NL, fn);
465  continue;
466  }
467  if (st.st_size == 0 || st.st_size > MAX_IMPORT_FILE_SIZE) { // FIXME: I limit here the max file size, but is there a sane limit?
468  DEBUGPRINT("SDCARD: CONTENT: skipping updating file \"%s\": too large (limit is %d bytes) or null-sized file" NL, fn, MAX_IMPORT_FILE_SIZE);
469  continue;
470  }
471  int ret = update_sdcard_file(entry->d_name, options, fn, -(int)st.st_size);
472  DEBUGPRINT("SDCARD: CONTENT: updated file \"%s\" status is %d" NL, fn, ret);
473  }
474  int ret = errno;
475  closedir(dir);
476  return ret;
477 }
478 
479 
480 #if 0
481 static int system_files_directory_update_item ( const char *dir_name, const char *fn_name, Uint8 *data, off_t size, int options )
482 {
483  int fd;
484  char fn[PATH_MAX];
485  int reinstall = 0;
486  snprintf(fn, sizeof fn, "%s" DIRSEP_STR "%s", dir_name, fn_name);
487  fd = open(fn, O_RDONLY | O_BINARY);
488  if (fd < 0) {
489  reinstall = 1;
490  } else {
491  off_t oft = xemu_safe_file_size_by_fd(fd);
492  if (oft == OFF_T_ERROR) {
493  }
494  if (oft != size)
495  reinstall = 1;
496  close(fd);
497  }
498  if ((options & SDCONENT_UPDATE_SYSDIR) && data && !reinstall)
499  reinstall = 1;
500  if (reinstall) {
501  if (!data) {
502  } else {
503  fd = open(fn, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666);
504  if (fd >= 0) {
505  xemu_safe_write(fd, data, size);
506  close(fd);
507  }
508  }
509  }
510  return 0;
511 }
512 
513 
514 static int system_files_directory_check ( const char *dir_name, int policy )
515 {
516  int ret = 0;
517  MKDIR(dir_name); // just in case, if it does not exist yet
518  // Check the two ROM FILES which are needed, but we can't include them in Xemu because of copyright reasons
519  // Data pointer being NULL signals that it's a check only, we have no source to create!
520  // Also, options/policy is zero. This is a must for calling this function in this situation:
521  system_files_directory_update_item(dir_name, MEGA65_ROM_NAME, NULL, MEGA65_ROM_SIZE, 0);
522  system_files_directory_update_item(dir_name, CHAR_ROM_NAME, NULL, CHAR_ROM_SIZE, 0);
523  // Update system files in the system directory of Xemu which can be generated by ourselves
524  Uint8 *d81 = xemu_malloc(D81_SIZE);
525  memset(d81, 0, D81_SIZE);
526  memcpy(d81 + 0x61800, d81_at_61800, sizeof d81_at_61800);
527  memcpy(d81 + 0x61900, d81_at_61900, sizeof d81_at_61900);
528  ret |= system_files_directory_update_item(dir_name, default_disk_image, d81, D81_SIZE, policy);
529  strcpy((char*)d81, xemu_external_d81_signature);
530  ret |= system_files_directory_update_item(dir_name, xemu_disk_image, d81, D81_SIZE, policy);
531  free(d81);
532  ret |= system_files_directory_update_item(dir_name, "BANNER.M65", meminitdata_banner, MEMINITDATA_BANNER_SIZE, policy);
533  ret |= system_files_directory_update_item(dir_name, "FREEZER.M65", meminitdata_freezer, MEMINITDATA_FREEZER_SIZE, policy);
534  return ret;
535 }
536 #endif
537 
538 
539 static const char xemu_sdcard_info_block_id[] = "XemuInfoBlock_PleaseDoNotDeleteOrModifyThanks";
540 
541 
542 int sdcontent_check_xemu_signature ( void )
543 {
544  Uint8 buffer[512];
545  int ret;
546  if (sdcard_read_block(XEMU_INFO_SDCARD_BLOCK_NO, buffer)) {
547  ret = -1;
548  goto end;
549  }
550  const int r = strlen(xemu_sdcard_info_block_id) + 1;
551  if (memcmp(xemu_sdcard_info_block_id, buffer, r)) {
552  ret = 0;
553  goto end;
554  }
555  ret = (int)(Uint32)(buffer[r] + (buffer[r + 1] << 8) + (buffer[r + 2] << 16) + (buffer[r + 3] << 24));
556 end:
557  DEBUGPRINT("SDCARD: check Xemu signature (@block %d): disk=%d this_xemu=%d" NL, XEMU_INFO_SDCARD_BLOCK_NO, ret, MEMCONTENT_VERSION_ID);
558  return ret;
559 }
560 
561 
562 static int sdcontent_put_xemu_signature ( void )
563 {
564  Uint8 buffer[512];
565  memset(buffer, 0, sizeof buffer);
566  strcpy((char*)buffer, xemu_sdcard_info_block_id);
567  const int r = strlen(xemu_sdcard_info_block_id) + 1;
568  buffer[r + 0] = ((MEMCONTENT_VERSION_ID) ) & 0xFF;
569  buffer[r + 1] = ((MEMCONTENT_VERSION_ID) >> 8) & 0xFF;
570  buffer[r + 2] = ((MEMCONTENT_VERSION_ID) >> 16) & 0xFF;
571  buffer[r + 3] = ((MEMCONTENT_VERSION_ID) >> 24) & 0xFF;
572  return sdcard_write_block(XEMU_INFO_SDCARD_BLOCK_NO, buffer);
573 }
574 
575 
576 int sdcontent_write_rom_stub ( void )
577 {
580  const int r = update_sdcard_file(MEGA65_ROM_NAME, SDCONTENT_SYS_FILE, (const char*)rom, MEGA65_ROM_SIZE);
581  free(rom);
582  return r;
583 }
584 
585 
586 // This function must be called after initializing SDcard, so it's safe for use to call sdcard_read_block() and sdcard_write_block()
587 int sdcontent_handle ( Uint32 size_in_blocks, const char *update_dir_path, int options )
588 {
589  static int init_done = 0;
590  //static char system_files_directory[PATH_MAX];
591  if (!init_done) {
592  //snprintf(system_files_directory, sizeof system_files_directory, "%s%s", sdl_pref_dir, "system-files");
594  init_done = 1;
595  }
596  //system_files_directory_check(system_files_directory, (options & SDCONTENT_UPDATE_SYSDIR));
597  /* ---- ROUND#1: check card, partitions, FS validity, fdisk/format card if needed ---- */
598  DEBUGPRINT("SDCARD: Reading MBR ..." NL);
599  if (sdcard_read_block(0, block))
600  FATAL("Cannot read MBR of SD-Card");
601  int do_fdisk = 0;
602  our_data_partition = -1;
603  if ((options & SDCONTENT_FORCE_FDISK)) {
604  do_fdisk = 1;
605  } else {
606  const char *p = NULL;
607  // If the MBR is ALL zero, it's clearly a sign it's an empty image, at least no partition table,
608  // would be unusable anyway that we can judge it as being subject of fdisk/format.
609  if (has_block_nonzero_byte(block)) {
610  // Though data partition is the first one created by THIS .c source, older existing
611  // images formatted with MEGA65's util itself has it as the second. Thus we just
612  // hear mfat_init_mbr()'s response, which gives us back the first VALID FAT32 partition,
613  // or -1 if fails to find any.
614  int part = mfat_init_mbr();
615  if (part < 0)
616  p = "No valid partition entry found for FAT32FS";
617  else if (mfat_use_part(part))
618  p = "Invalid/bad FAT32FS on the data partition";
619  else {
620  our_data_partition = part;
621  DEBUGPRINT("SDCARD: assumed data FAT32FS partition: #%d" NL, part);
622  }
623  } else
624  p = "Empty MBR (new/empty image?)";
625  // FIXME: maybe check/validate system partition as well?
626  if (p) {
627  if ((options & SDCONTENT_ASK_FDISK)) {
628  char msg[256];
629  snprintf(msg, sizeof msg, "SD-card image seems to have invalid format!\nReason: %s\nCan I format it?\nALL DATA WILL BE LOST!", p);
630  do_fdisk = ARE_YOU_SURE(msg, 0);
631  } else
632  DEBUGPRINT("SDCARD: WARNING(SDCONTENT_ASK_FDISK was not requested, but problem detected): %s" NL, p);
633  }
634  }
635  if (do_fdisk) {
636  //FATAL("YAY, DOING FDISK!");
637  if (fdisk(size_in_blocks))
638  return -1;
639  }
640  if ((options & (SDCONTENT_FORCE_FDISK | SDCONTENT_ASK_FDISK)) && (our_data_partition < 0)) {
641  ERROR_WINDOW("Warning! SD-card image content (partitions/fat32fs) seems to be invalid!\nCannot proceed with further SD-card Xemu FS level operations!");
642  return -1;
643  }
644  if (our_data_partition >= 0) {
645  DEBUGPRINT("SDCARD: great, it seems the card format is valid." NL);
646  // Use the root directory of FATFS associated with the "sd_rootdirent" obj, so we can use to find/etc stuffs in root dir then
647  mfat_open_rootdir(&sd_rootdirent.stream);
648  }
649  /* ---- ROUND#2: check important system files (if requested) ---- */
650  options &= SDCONTENT_ASK_FILES | SDCONTENT_DO_FILES | SDCONTENT_OVERWRITE_FILES; // no more rounds, so we mask output to the important remaing ones
651  if (options) {
652  if (our_data_partition < 0)
653  FATAL("System file update/check requested, but format/FS was not validated!");
654  //update_from_directory(system_files_directory, options);
655  char rom_path[PATH_MAX];
656  snprintf(rom_path, sizeof rom_path, "%s%s", sdl_pref_dir, MEGA65_ROM_NAME);
657  int r = 0;
658  r |= update_sdcard_file(MEGA65_ROM_NAME, options | SDCONTENT_SYS_FILE, rom_path, -MEGA65_ROM_SIZE);
659  snprintf(rom_path, sizeof rom_path, "%s%s", sdl_pref_dir, CHAR_ROM_NAME);
660  r |= update_sdcard_file(CHAR_ROM_NAME, options | SDCONTENT_SYS_FILE, rom_path, -CHAR_ROM_SIZE);
661 
662  // Update system files based on the structure in memcontent.c and .h
663  for (int a = 0; a < MEMINITDATA_SDFILES_ITEMS; a++)
664  r |= update_sdcard_file(meminitdata_sdfiles_db[a].fn, options, (const char*)meminitdata_sdfiles_db[a].p, meminitdata_sdfiles_db[a].size);
665  //r |= update_sdcard_file("BANNER.M65", options, (const char*)meminitdata_banner, MEMINITDATA_BANNER_SIZE);
666  //r |= update_sdcard_file("FREEZER.M65", options, (const char*)meminitdata_freezer, MEMINITDATA_FREEZER_SIZE);
667  char *d81 = (char*)d81access_create_image(NULL, "D81 ON <SDCARD>!", 0);
668  // FIXME: deactivated now: no need for template, Xemu can create&mount D81s! (maybe we should remove this)
669  // ... also it's very confusing since template would have disk label D81 ON SDCARD as well, confusing people a lot
670  //xemu_save_file("@template.d81", d81, D81_SIZE, NULL);
671  r |= update_sdcard_file(default_disk_image, options, d81, D81_SIZE);
672  strcpy(d81, xemu_external_d81_signature);
673  r |= update_sdcard_file(xemu_disk_image, options, d81, D81_SIZE);
674  free(d81);
675  if (r)
676  ERROR_WINDOW("Some error occured while updating your SD-card image file!");
677  else
678  sdcontent_put_xemu_signature();
679  }
680  /* ---- ROUND#3: update user specified files (if any) ---- */
681  if (update_dir_path) {
682  if (our_data_partition < 0)
683  FATAL("User directory based file update/check requested, but format/FS was not validated!");
684  return update_from_directory(update_dir_path, SDCONTENT_OVERWRITE_FILES);
685  }
686  return 0;
687 }
688 
689 #endif
mfat_dirent_t
Definition: fat32.h:60
mfat_init
void mfat_init(mfat_io_callback_func_t reader, mfat_io_callback_func_t writer, Uint32 device_size)
Definition: fat32.c:323
CHAR_ROM_SIZE
#define CHAR_ROM_SIZE
Definition: mega65.h:36
XEMU_STUB_ROM_SAVE_FILENAME
#define XEMU_STUB_ROM_SAVE_FILENAME
Definition: rom.h:21
emutools.h
mfat_open_rootdir
void mfat_open_rootdir(mfat_stream_t *p)
Definition: fat32.c:542
MEMINITDATA_FREEZER_SIZE
#define MEMINITDATA_FREEZER_SIZE
Definition: memcontent.h:47
OFF_T_ERROR
#define OFF_T_ERROR
Definition: fat32.c:42
O_BINARY
#define O_BINARY
Definition: emutools_basicdefs.h:140
mfat_use_part
int mfat_use_part(int part)
Definition: fat32.c:406
fd
int fd
Definition: hdos.c:62
mfat_init_mbr
int mfat_init_mbr(void)
Definition: fat32.c:339
meminitdata_freezer
const Uint8 meminitdata_freezer[MEMINITDATA_FREEZER_SIZE]
Definition: memcontent.c:6824
fn
const char * fn
Definition: roms.c:42
MEGA65_ROM_SIZE
#define MEGA65_ROM_SIZE
Definition: mega65.h:34
m65-memcontent-generator.data
data
Definition: m65-memcontent-generator.py:119
mega65.h
Uint32
uint32_t Uint32
Definition: fat32.c:49
sdcontent.h
MEMINITDATA_BANNER_SIZE
#define MEMINITDATA_BANNER_SIZE
Definition: memcontent.h:35
Uint8
uint8_t Uint8
Definition: fat32.c:51
D81_SIZE
#define D81_SIZE
Definition: d81access.h:22
block
Uint32 block
Definition: fat32.c:156
xemu_safe_file_size_by_fd
off_t xemu_safe_file_size_by_fd(int fd)
Definition: emutools_files.c:583
emutools_files.h
xemu_malloc
void * xemu_malloc(size_t size)
Definition: emutools.c:226
DEBUGPRINT
#define DEBUGPRINT(...)
Definition: emutools_basicdefs.h:171
sdcard_write_block
int sdcard_write_block(Uint32 block, Uint8 *buffer)
Definition: sdcard.c:569
options
int options
Definition: cpmfs.c:41
d81access_create_image
Uint8 * d81access_create_image(Uint8 *img, const char *diskname, const int name_from_fn)
Definition: d81access.c:604
dir
DIR * dir
Definition: cpmfs.c:46
ERROR_WINDOW
#define ERROR_WINDOW(...)
Definition: xep128.h:116
NL
#define NL
Definition: fat32.c:37
compress_sd_image.r
def r
Definition: compress_sd_image.py:76
rom.h
PRINTF_LLD
#define PRINTF_LLD
Definition: emutools_basicdefs.h:145
xemu_safe_read
ssize_t xemu_safe_read(int fd, void *buffer, size_t length)
Definition: emutools_files.c:543
mfat_dirent_t::stream
mfat_stream_t stream
Definition: fat32.h:61
DIRSEP_STR
#define DIRSEP_STR
Definition: emutools_basicdefs.h:141
size
int size
Definition: inject.c:37
ARE_YOU_SURE
int ARE_YOU_SURE(const char *s, int flags)
Definition: emutools.c:1202
MKDIR
#define MKDIR(__n)
Definition: emutools_basicdefs.h:147
meminitdata_banner
const Uint8 meminitdata_banner[MEMINITDATA_BANNER_SIZE]
Definition: memcontent.c:1703
MEMINITDATA_SDFILES_ITEMS
#define MEMINITDATA_SDFILES_ITEMS
Definition: memcontent.h:19
mfat_overwrite_file_with_direct_linear_device_block_write
Uint32 mfat_overwrite_file_with_direct_linear_device_block_write(mfat_dirent_t *dirent, const char *name, Uint32 size)
Definition: fat32.c:813
memcontent.h
Uint16
uint16_t Uint16
Definition: fat32.c:50
fat32.h
meminitdata_sdfiles_db
const struct meminitdata_sdfiles_st meminitdata_sdfiles_db[MEMINITDATA_SDFILES_ITEMS]
Definition: memcontent.c:13
CHAR_ROM_NAME
#define CHAR_ROM_NAME
Definition: mega65.h:35
sdcard_read_block
int sdcard_read_block(Uint32 block, Uint8 *buffer)
Definition: sdcard.c:548
MEMCONTENT_VERSION_ID
#define MEMCONTENT_VERSION_ID
Definition: memcontent.h:15
xemu_safe_write
ssize_t xemu_safe_write(int fd, const void *buffer, size_t length)
Definition: emutools_files.c:563
xemu_external_d81_signature
const char xemu_external_d81_signature[]
Definition: sdcard.c:84
sdl_pref_dir
char * sdl_pref_dir
Definition: emutools.c:97
FATAL
#define FATAL(...)
Definition: xep128.h:117
ofs
int ofs
Definition: fat32.c:158
MEGA65_ROM_NAME
#define MEGA65_ROM_NAME
Definition: mega65.h:33
rom_make_xemu_stub_rom
void rom_make_xemu_stub_rom(Uint8 *rom, const char *save_file)
Definition: rom.c:132
part
int part
Definition: fat32.c:74
rom
char * rom
Definition: rc2014.c:38
d81access.h
st
struct stat st
Definition: cpmfs.c:43