diff --git a/reactos/tools/.cvsignore b/reactos/tools/.cvsignore index b15aa2b4aef..28e71f2f914 100644 --- a/reactos/tools/.cvsignore +++ b/reactos/tools/.cvsignore @@ -6,6 +6,7 @@ rline rmkdir rrmdir mkconfig +mkflpimg rdel rsym rtouch diff --git a/reactos/tools/Makefile b/reactos/tools/Makefile index 9197219a0eb..fc31b757b27 100644 --- a/reactos/tools/Makefile +++ b/reactos/tools/Makefile @@ -9,7 +9,8 @@ TOOLS = \ rmkdir$(EXE_POSTFIX) \ rrmdir$(EXE_POSTFIX) \ rsym$(EXE_POSTFIX) \ - rtouch$(EXE_POSTFIX) + rtouch$(EXE_POSTFIX) \ + mkflpimg$(EXE_POSTFIX) CLEAN_FILES = $(TOOLS) @@ -79,6 +80,15 @@ rtouch$(EXE_POSTFIX): rtouch.c $(HOST_CC) $(CFLAGS) -DDOS_PATHS rtouch.c -o rtouch$(EXE_POSTFIX) endif +ifeq ($(HOST),mingw32-linux) +rtouch$(EXE_POSTFIX): mkflpimg.c + $(HOST_CC) $(CFLAGS) -DUNIX_PATHS mkflpimg.c -o mkflpimg$(EXE_POSTFIX) +endif +ifeq ($(HOST),mingw32-windows) +rtouch$(EXE_POSTFIX): mkflpimg.c + $(HOST_CC) $(CFLAGS) -DDOS_PATHS mkflpimg.c -o mkflpimg$(EXE_POSTFIX) +endif + wmc_directory_target: $(MAKE) -C wmc wmc$(EXE_POSTFIX) diff --git a/reactos/tools/mkflpimg.c b/reactos/tools/mkflpimg.c new file mode 100644 index 00000000000..fbbe65f17e5 --- /dev/null +++ b/reactos/tools/mkflpimg.c @@ -0,0 +1,347 @@ +#include +#include +#include +#include +#include + +#define N_CYLINDERS 80 +#define ROOT_ENTRY_SIZE 32 + +#define SECTOR_SIZE 512 +#define SECTORS_PER_CLUSTER 1 +#define N_RESERVED 1 +#define N_FATS 2 +#define N_ROOT_ENTRIES 224 +#define SECTORS_PER_DISK (N_HEADS * N_CYLINDERS * SECTORS_PER_TRACK) +#define MEDIA_TYPE 0xf0 +#define SECTORS_PER_FAT 9 +#define SECTORS_PER_TRACK 18 +#define N_HEADS 2 +#define SIGNATURE 0x29 /* only MS? */ +#define END_SIGNATURE 0xaa55 + + +#define ATTR_READONLY 0x01 +#define ATTR_HIDDEN 0x02 +#define ATTR_SYSTEM 0x04 +#define ATTR_VOLUME 0x08 +#define ATTR_SUBDIR 0x10 +#define ATTR_ARCHIVE 0x20 +#define ATTR_RES1 0x40 +#define ATTR_RES2 0x80 + + +typedef unsigned char disk_sector_t[SECTOR_SIZE]; + +typedef struct boot_sector +{ + unsigned short jmp; + unsigned char nop; + char oem[8]; + unsigned short bytes_per_sector; + unsigned char sectors_per_cluster; + unsigned short reserved_sectors; + unsigned char n_fats; + unsigned short n_root_entries; + unsigned short n_sectors; + unsigned char media_type; + unsigned short sectors_per_fat; + unsigned short sectors_per_track; + unsigned short n_heads; + unsigned long hidden_sectors; + unsigned long huge_sectors; + unsigned char drive; + unsigned char reserved; + unsigned char signature; + unsigned long volume_id; + char volume_label[11]; + char file_system[8]; + unsigned char boot_code[SECTOR_SIZE - 62 - 2]; + unsigned short end_signature; +} __attribute__ ((packed)) boot_sector_t; + + +typedef struct root_entry +{ + char name[8]; + char extension[3]; + unsigned char attribute; + unsigned char reserved[10]; + unsigned short time; + unsigned short date; + unsigned short cluster; + unsigned long size; +} __attribute ((packed)) root_entry_t; + + +disk_sector_t *new_image(char *bsfname) +{ + FILE *bsf; + disk_sector_t *img; + boot_sector_t boot_sec; + root_entry_t *root; + + if ((bsf = fopen(bsfname, "rb")) == NULL) + { + printf("Boot sector image file %s not found!\n", bsfname); + return NULL; + } + if (fread(&boot_sec, 1, SECTOR_SIZE, bsf) != SECTOR_SIZE) + { + printf("Unable to read boot sector image file %s!\n", bsfname); + fclose(bsf); + return NULL; + } + fclose(bsf); + + if ( (boot_sec.bytes_per_sector != SECTOR_SIZE) || + (boot_sec.sectors_per_cluster != SECTORS_PER_CLUSTER) || + (boot_sec.reserved_sectors != N_RESERVED) || + (boot_sec.n_fats != N_FATS) || + (boot_sec.n_root_entries != N_ROOT_ENTRIES) || + (boot_sec.n_sectors != SECTORS_PER_DISK) || + (boot_sec.media_type != MEDIA_TYPE) || + (boot_sec.sectors_per_fat != SECTORS_PER_FAT) || + (boot_sec.sectors_per_track != SECTORS_PER_TRACK) || + (boot_sec.n_heads != N_HEADS) || +// (boot_sec.signature != SIGNATURE) || + (boot_sec.end_signature != END_SIGNATURE) ) + { + printf("Invalid boot sector in file %s\n", bsfname); + return NULL; + } + + if ((img = (disk_sector_t *)malloc(SECTOR_SIZE * SECTORS_PER_DISK)) == NULL) + { + printf("Not enough memory!\n"); + return NULL; + } + + memset(img, 0, SECTOR_SIZE * SECTORS_PER_TRACK); + memcpy(img, &boot_sec, SECTOR_SIZE); + + root = (root_entry_t *)img[N_RESERVED + N_FATS * SECTORS_PER_FAT]; + strncpy(root->name, "REACTOS ", 11); + root->attribute = ATTR_VOLUME; + + return img; +} + + +void create_root_entry(root_entry_t *root, char *fname, + unsigned short cluster, unsigned long size) +{ + int i, j; + time_t t; + struct tm *localt; + + i = 0; + j = 0; + while ((fname[j] != '\0') && (fname[j] != '.') && (i < 8)) + { + root->name[i] = toupper(fname[j]); + i++; + j++; + } + while (i < 8) + { + root->name[i] = ' '; + i++; + } + if (fname[j] == '.') + { + i = 0; + j++; + while ((fname[j] != '\0') && (i < 3)) + { + root->extension[i] = toupper(fname[j]); + i++; + j++; + } + while (i < 3) + { + root->extension[i] = ' '; + i++; + } + } + else + { + i = 0; + while (i < 3) + { + root->extension[i] = ' '; + i++; + } + } + + root->attribute = ATTR_ARCHIVE; + t = time(0); + localt = localtime(&t); + root->time = (((localt->tm_hour & 0x001f) << 11) | + ((localt->tm_min & 0x003f) << 5) | + ((localt->tm_sec / 2) & 0x001f)); + root->date = ((((localt->tm_year - 1980) & 0x007f) << 9) | + (((localt->tm_mon + 1) & 0x000f) << 5) | + (localt->tm_mday & 0x001f)); + root->cluster = cluster; + root->size = size; +} + + +void update_fat(unsigned char *fat, int cl_start, int cl_end) +{ + int i, k; + unsigned short *cl; + + for (i = cl_start; i < cl_end - 1; i++) + { + k = (i - 2) * 3 / 2; + cl = ((unsigned short *)&fat[k]); + if (i & 1) + { + *cl = (*cl & 0x000f) | (((i + 1) & 0x0fff) << 4); + } + else + { + *cl = (*cl & 0xf000) | ((i + 1) & 0x0fff); + } + } + k = (i - 2) * 3 / 2; + cl = ((unsigned short *)&fat[k]); + if (i & 1) + { + *cl = (*cl & 0x000f) | 0xfff0; + } + else + { + *cl = (*cl & 0xf000) | 0x0fff; + } +} + + +int copy_files(disk_sector_t *img, char *filenames[], int n_files) +{ + int i, k; + FILE *f; + int cl_start, cl_end; + unsigned char *fat1, *fat2; + root_entry_t *root; + unsigned long n, size; + + fat1 = (unsigned char *)img[N_RESERVED]; + fat2 = (unsigned char *)img[N_RESERVED + SECTORS_PER_FAT]; + root = (root_entry_t *)img[N_RESERVED + N_FATS * SECTORS_PER_FAT]; + + k = N_RESERVED + + N_FATS * SECTORS_PER_FAT + + N_ROOT_ENTRIES * ROOT_ENTRY_SIZE / SECTOR_SIZE; + + cl_end = 1; + + if (n_files > N_ROOT_ENTRIES) + { + n_files = N_ROOT_ENTRIES; + } + + for (i = 0; i < n_files; i++) + { + cl_start = cl_end + 1; + if ((f = fopen(filenames[i], "rb")) == NULL) + { + printf("Error opening file %s!", filenames[i]); + return 1; + } + + printf(" %s\n", filenames[i]); + + size = 0; + while ((n = fread(img[k], 1, SECTOR_SIZE, f)) > 0) + { + size += n; + cl_end++; + k++; + } + fclose(f); + + root++; + create_root_entry(root, filenames[i], cl_start, size); + + update_fat(fat1, cl_start, cl_end); + } + memcpy(fat2, fat1, SECTORS_PER_FAT * SECTOR_SIZE); + + return 0; +} + + +int write_image(disk_sector_t *img, char *imgname) +{ + FILE *f; + + if ((f = fopen(imgname, "rb")) != NULL) + { + printf("Image file %s already exists!\n", imgname); + fclose(f); + free(img); + return 1; + } + + f = fopen(imgname, "wb"); + if (fwrite(img, SECTOR_SIZE, SECTORS_PER_DISK, f) != SECTORS_PER_DISK) + { + printf("Unable to write image file %s\n!", imgname); + fclose(f); + free(img); + return 1; + } + fclose(f); + + free(img); + return 0; +} + + +int main(int argc, char *argv[]) +{ + disk_sector_t *img; + char *imgname; + char *bsfname; + char **filenames; + int n_files; + + if (argc < 4) + { + printf("Usage: mkflpimg \n"); + return 1; + } + + imgname = argv[1]; + bsfname = argv[2]; + filenames = &argv[3]; + n_files = argc - 3; + + printf("Creating image ...\n"); + if ((img = new_image(bsfname)) == NULL) + { + return 1; + } + + printf("Copying files ...\n"); + + if (copy_files(img, filenames, n_files)) + { + return 1; + } + + printf("Writing image file ...\n"); + + if (write_image(img, imgname)) + { + return 1; + } + + printf("Finished.\n"); + + return 0; +} +