Author: hbelusca Date: Wed Sep 9 02:11:49 2015 New Revision: 69139
URL: http://svn.reactos.org/svn/reactos?rev=69139&view=rev Log: OMGWTFBBQ!!!! We can now boot our ISOs on UEFI systems!! Thanks gigaherz for the "fatten" utility!, and others for testing.
[CDMAKE] - Add multi-boot CD support, following El-Torito specification, such that we can the usual ISO boot sector on BIOS-based PCs, and the UEFI loader on UEFI-based PCs. - Load segment should be stored in little endian. - Fix the computation of the sector count (count in 512 byte sectors and rounded up). - Rework the command-line options to make them more compatible with CDIMAGE / OSCDIMG. CORE-10120
[BOOTDATA] - Activate the UEFI boot support for our ISOs.
Modified: trunk/reactos/boot/CMakeLists.txt trunk/reactos/tools/cdmake/cdmake.c trunk/reactos/tools/cdmake/config.h trunk/reactos/tools/cdmake/dirhash.c trunk/reactos/tools/cdmake/dirhash.h
Modified: trunk/reactos/boot/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/CMakeLists.txt?rev=691... ============================================================================== --- trunk/reactos/boot/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/boot/CMakeLists.txt [iso-8859-1] Wed Sep 9 02:11:49 2015 @@ -16,7 +16,7 @@ endif()
add_custom_target(efisys - COMMAND native-fatten ${CMAKE_CURRENT_BINARY_DIR}/efisys.bin -format 2880 -boot ${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/fat.bin -mkdir EFI -mkdir EFI/BOOT -add $<TARGET_FILE:bootmgfw> EFI/BOOT/boot${EFI_PLATFORM_ID}.EFI + COMMAND native-fatten ${CMAKE_CURRENT_BINARY_DIR}/efisys.bin -format 2880 -boot ${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/fat.bin -mkdir EFI -mkdir EFI/BOOT -add $<TARGET_FILE:bootmgfw> EFI/BOOT/boot${EFI_PLATFORM_ID}.efi DEPENDS native-fatten bootmgfw fat VERBATIM)
@@ -25,8 +25,7 @@ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bootcd.lst "")
add_custom_target(bootcd -# COMMAND native-cdmake -j -m -bootdata:2#p0,e,b${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isoboot.bin#pEF,e,b${CMAKE_CURRENT_BINARY_DIR}/efisys.bin @${CMAKE_CURRENT_BINARY_DIR}/bootcd.lst REACTOS ${REACTOS_BINARY_DIR}/bootcd.iso - COMMAND native-cdmake -j -m -b ${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isoboot.bin @${CMAKE_CURRENT_BINARY_DIR}/bootcd.lst REACTOS ${REACTOS_BINARY_DIR}/bootcd.iso + COMMAND native-cdmake -j -m -bootdata:2#p0,e,b${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isoboot.bin#pEF,e,b${CMAKE_CURRENT_BINARY_DIR}/efisys.bin @${CMAKE_CURRENT_BINARY_DIR}/bootcd.lst REACTOS ${REACTOS_BINARY_DIR}/bootcd.iso DEPENDS native-cdmake efisys VERBATIM)
@@ -35,8 +34,8 @@ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bootcdregtest.lst "")
add_custom_target(bootcdregtest - COMMAND native-cdmake -j -m -b ${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isobtrt.bin @${CMAKE_CURRENT_BINARY_DIR}/bootcdregtest.lst REACTOS ${REACTOS_BINARY_DIR}/bootcdregtest.iso - DEPENDS native-cdmake + COMMAND native-cdmake -j -m -bootdata:2#p0,e,b${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isobtrt.bin#pEF,e,b${CMAKE_CURRENT_BINARY_DIR}/efisys.bin @${CMAKE_CURRENT_BINARY_DIR}/bootcdregtest.lst REACTOS ${REACTOS_BINARY_DIR}/bootcdregtest.iso + DEPENDS native-cdmake efisys VERBATIM)
##livecd @@ -49,8 +48,8 @@ file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/livecd.lst "Profiles/Default User/Start Menu/Programs\n")
add_custom_target(livecd - COMMAND native-cdmake -j -m -b ${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isoboot.bin @${CMAKE_CURRENT_BINARY_DIR}/livecd.lst REACTOS ${REACTOS_BINARY_DIR}/livecd.iso - DEPENDS native-cdmake + COMMAND native-cdmake -j -m -bootdata:2#p0,e,b${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isoboot.bin#pEF,e,b${CMAKE_CURRENT_BINARY_DIR}/efisys.bin @${CMAKE_CURRENT_BINARY_DIR}/livecd.lst REACTOS ${REACTOS_BINARY_DIR}/livecd.iso + DEPENDS native-cdmake efisys VERBATIM)
##hybridcd @@ -63,11 +62,10 @@ file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/hybridcd.lst "livecd/Profiles/Default User/Start Menu/Programs\n")
add_custom_target(hybridcd - COMMAND native-cdmake -j -m -b ${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isoboot.bin @${CMAKE_CURRENT_BINARY_DIR}/hybridcd.lst REACTOS ${REACTOS_BINARY_DIR}/hybridcd.iso - DEPENDS native-cdmake bootcd livecd + COMMAND native-cdmake -j -m -bootdata:2#p0,e,b${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isoboot.bin#pEF,e,b${CMAKE_CURRENT_BINARY_DIR}/efisys.bin @${CMAKE_CURRENT_BINARY_DIR}/hybridcd.lst REACTOS ${REACTOS_BINARY_DIR}/hybridcd.iso + DEPENDS native-cdmake efisys bootcd livecd VERBATIM)
add_subdirectory(freeldr) add_subdirectory(bootdata) add_subdirectory(environ) -
Modified: trunk/reactos/tools/cdmake/cdmake.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/tools/cdmake/cdmake.c?rev=6... ============================================================================== --- trunk/reactos/tools/cdmake/cdmake.c [iso-8859-1] (original) +++ trunk/reactos/tools/cdmake/cdmake.c [iso-8859-1] Wed Sep 9 02:11:49 2015 @@ -68,6 +68,7 @@ #include "config.h" #include "dirhash.h"
+// FIXME! FIXME! Do it in a portable way!! typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; @@ -83,8 +84,8 @@ #define SECTOR_SIZE 2048 #define BUFFER_SIZE (8 * SECTOR_SIZE)
-const BYTE HIDDEN_FLAG = 1; -const BYTE DIRECTORY_FLAG = 2; +#define HIDDEN_FLAG 1 +#define DIRECTORY_FLAG 2
struct cd_image @@ -96,6 +97,35 @@ char filespecs[128]; BYTE *buffer; }; + +typedef struct _boot_validation_header +{ + BYTE header_id; + BYTE platform_id; +} BOOT_VALIDATION_HEADER, *PBOOT_VALIDATION_HEADER; + +typedef struct boot_entry +{ + struct boot_entry *next_entry; + BYTE boot_id; + BYTE boot_emu_type; + WORD load_segment; + BYTE system_type; + WORD sector_count; // boot_image_size + DWORD load_rba; // boot_image_sector + // BYTE unused[20]; + char bootimage[512]; +} BOOT_ENTRY, *PBOOT_ENTRY; + +typedef struct boot_header +{ + struct boot_header *next_header; + BYTE header_id; + BYTE platform_id; + WORD num_entries; + // char id_string[28]; + PBOOT_ENTRY entry_list; +} BOOT_HEADER, *PBOOT_HEADER;
typedef struct date_and_time { @@ -166,11 +196,12 @@ DWORD number_of_directories; DWORD bytes_in_directories;
-BOOL eltorito; +BOOL eltorito; // TRUE/FALSE: bootable/non-bootable CD-ROM +BOOL multi_boot; // TRUE/FALSE: multi/single-boot CD-ROM DWORD boot_catalog_sector; -DWORD boot_image_sector; -WORD boot_image_size; // counted in 512 byte sectors -char bootimage[512]; +BOOT_VALIDATION_HEADER boot_validation_header; +BOOT_ENTRY default_boot_entry; +PBOOT_HEADER boot_header_list;
BOOL joliet; DWORD joliet_path_table_size; @@ -213,10 +244,24 @@
static void release_memory(void) { + while (boot_header_list) + { + PBOOT_HEADER next_header = boot_header_list->next_header; + + while (boot_header_list->entry_list) + { + PBOOT_ENTRY next_entry = boot_header_list->entry_list->next_entry; + free(boot_header_list->entry_list); + boot_header_list->entry_list = next_entry; + } + + free(boot_header_list); + boot_header_list = next_header; + } + while (root.next_in_memory != NULL) { - struct directory_record *next = - root.next_in_memory->next_in_memory; + PDIR_RECORD next = root.next_in_memory->next_in_memory; if (joliet) free(root.next_in_memory->joliet_name); free(root.next_in_memory); @@ -224,6 +269,7 @@ } if (joliet) free(root.joliet_name); + if (cd.buffer != NULL) { free(cd.buffer); @@ -236,7 +282,7 @@ error exit point in main(). -----------------------------------------------------------------------------*/
-void error_exit(const char* fmt, ...) +static void error_exit(const char* fmt, ...) { va_list arg;
@@ -356,7 +402,7 @@ write_byte(*s++); }
-static void write_bytecounted_string(unsigned bytecount, char *s) +static void write_bytecounted_string(unsigned bytecount, char *s, char padding) { while (*s != 0 && bytecount != 0) { @@ -365,7 +411,7 @@ } while (bytecount != 0) { - write_byte(' '); + write_byte(padding); bytecount--; } } @@ -383,7 +429,7 @@ } }
-static void write_bytecounted_string_as_big_endian_unicode(unsigned bytecount, char *s) +static void write_bytecounted_string_as_big_endian_unicode(unsigned bytecount, char *s, char padding) { unsigned wordcount = bytecount / 2;
@@ -394,12 +440,12 @@ } while (wordcount != 0) { - write_big_endian_word(' '); + write_big_endian_word(padding); wordcount--; }
if (bytecount % 2 != 0) - write_byte(' '); + write_byte(padding); }
/*----------------------------------------------------------------------------- @@ -497,7 +543,7 @@ write_byte(d->flags); write_byte(0); // file unit size for an interleaved file write_byte(0); // interleave gap size for an interleaved file - write_both_endian_word((WORD) 1); // volume sequence number + write_both_endian_word(1); // volume sequence number write_byte((BYTE)identifier_size); switch (DirType) { @@ -575,7 +621,7 @@ #define strcasecmp stricmp #endif//_WIN32
-BOOL cdname_exists(PDIR_RECORD d) +static BOOL cdname_exists(PDIR_RECORD d) { PDIR_RECORD p = d->parent->first_record; while (p) @@ -589,7 +635,7 @@ return FALSE; }
-void parse_filename_into_dirrecord(const char* filename, PDIR_RECORD d, BOOL dir) +static void parse_filename_into_dirrecord(const char* filename, PDIR_RECORD d, BOOL dir) { const char *s = filename; char *t = d->name_on_cd; @@ -608,7 +654,8 @@ if ((size_t)(t-d->name_on_cd) < sizeof(d->name_on_cd)-1) *t++ = check_for_punctuation(*s, filename); else if (!joliet) - error_exit("'%s' is not ISO-9660, aborting...", filename); + error_exit("'%s' is not ISO-9660, aborting...", filename); + if ((size_t)(n-d->name) < sizeof(d->name)-1) *n++ = *s; else if (!joliet) @@ -914,7 +961,7 @@ else { if (!getcwd(buf, sizeof(buf))) - error_exit("Can't get CWD: %s\n", strerror(errno)); + error_exit("Cannot get CWD: %s\n", strerror(errno)); strcat(buf, DIR_SEPARATOR_STRING); strcat(buf, source); strcat(buf, entry->d_name); @@ -922,7 +969,7 @@
if (stat(buf, &stbuf) == -1) { - error_exit("Can't access '%s' (%s)\n", buf, strerror(errno)); + error_exit("Cannot access '%s' (%s)\n", buf, strerror(errno)); return; }
@@ -944,7 +991,7 @@ } else { - error_exit("Can't open %s\n", source); + error_exit("Cannot open %s\n", source); return; }
@@ -976,14 +1023,14 @@ else { if (!getcwd(buf, sizeof(buf))) - error_exit("Can't get CWD: %s\n", strerror(errno)); + error_exit("Cannot get CWD: %s\n", strerror(errno)); strcat(buf, DIR_SEPARATOR_STRING); strcat(buf, source); }
if (stat(buf, &stbuf) == -1) { - error_exit("Can't access '%s' (%s)\n", buf, strerror(errno)); + error_exit("Cannot access '%s' (%s)\n", buf, strerror(errno)); return; } new_d = new_directory_record(entry, &stbuf, d); @@ -1004,7 +1051,7 @@ } else { - error_exit("Can't open %s\n", source); + error_exit("Cannot open %s\n", source); return; }
@@ -1028,7 +1075,7 @@ else { if (!getcwd(buf, sizeof(buf))) - error_exit("Can't get CWD: %s\n", strerror(errno)); + error_exit("Cannot get CWD: %s\n", strerror(errno)); strcat(buf, DIR_SEPARATOR_STRING); strcat(buf, source); strcat(buf, entry->d_name); @@ -1036,7 +1083,7 @@
if (stat(buf, &stbuf) == -1) { - error_exit("Can't access '%s' (%s)\n", buf, strerror(errno)); + error_exit("Cannot access '%s' (%s)\n", buf, strerror(errno)); return; }
@@ -1087,7 +1134,7 @@ } else { - error_exit("Can't open %s\n", source); + error_exit("Cannot open %s\n", source); return; }
@@ -1172,18 +1219,18 @@ FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { - error_exit("Can't open timestamp file %s\n", file->source_name); + error_exit("Cannot open timestamp file %s\n", file->source_name); }
if (!get_cd_file_time(open_file, &d->date_and_time)) { - error_exit("Can't stat timestamp file %s\n", file->source_name); + error_exit("Cannot stat timestamp file %s\n", file->source_name); } CloseHandle(open_file); #else if (stat(file->target_name, &stbuf) == -1) { - error_exit("Can't stat timestamp file %s\n", file->source_name); + error_exit("Cannot stat timestamp file %s\n", file->source_name); } convert_date_and_time(&d->date_and_time, &stbuf.st_ctime); #endif @@ -1208,15 +1255,15 @@ FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { - error_exit("Can't open file %s\n", file->source_name); + error_exit("Cannot open file %s\n", file->source_name); } if (!get_cd_file_time(open_file, &new_d->date_and_time)) { - error_exit("Can't stat file %s\n", file->source_name); + error_exit("Cannot stat file %s\n", file->source_name); } if (!GetFileSizeEx(open_file, &file_size)) { - error_exit("Can't get file size of %s\n", file->source_name); + error_exit("Cannot get file size of %s\n", file->source_name); } new_d->size = new_d->joliet_size = file_size.QuadPart; new_d->orig_name = file->source_name; @@ -1224,7 +1271,7 @@ #else if (stat(file->source_name, &stbuf) == -1) { - error_exit("Can't find '%s' (target %s)\n", + error_exit("Cannot find '%s' (target %s)\n", file->source_name, file->target_name); } @@ -1296,24 +1343,32 @@
static BOOL write_from_file(FILE *file, DWORD size) { - int n; - - fseek(file, 0, SEEK_SET); - while (size > 0) - { - n = BUFFER_SIZE - cd.count; - if ((DWORD)n > size) - n = size; - - if (fread(cd.buffer + cd.count, n, 1, file) < 1) - return FALSE; - - cd.count += n; - if (cd.count == BUFFER_SIZE) - flush_buffer(); - cd.sector += n / SECTOR_SIZE; - cd.offset += n % SECTOR_SIZE; - size -= n; + if (cd.file != NULL) + { + int n; + + fseek(file, 0, SEEK_SET); + while (size > 0) + { + n = BUFFER_SIZE - cd.count; + if ((DWORD)n > size) + n = size; + + if (fread(cd.buffer + cd.count, n, 1, file) < 1) + return FALSE; + + cd.count += n; + if (cd.count == BUFFER_SIZE) + flush_buffer(); + cd.sector += n / SECTOR_SIZE; + cd.offset += n % SECTOR_SIZE; + size -= n; + } + } + else + { + cd.sector += size / SECTOR_SIZE; + cd.offset += size % SECTOR_SIZE; }
return TRUE; @@ -1341,30 +1396,30 @@
write_string("\1CD001\1"); write_byte(0); - write_bytecounted_string(32, ""); // system identifier - write_bytecounted_string(32, volume_label); // volume label + write_bytecounted_string(32, "", ' '); // system identifier + write_bytecounted_string(32, volume_label, ' '); // volume label
write_block(8, 0); write_both_endian_dword(total_sectors); write_block(32, 0); - write_both_endian_word((WORD) 1); // volume set size - write_both_endian_word((WORD) 1); // volume sequence number - write_both_endian_word((WORD) 2048); // sector size + write_both_endian_word(1); // volume set size + write_both_endian_word(1); // volume sequence number + write_both_endian_word(2048); // sector size write_both_endian_dword(path_table_size); write_little_endian_dword(little_endian_path_table_sector); - write_little_endian_dword((DWORD) 0); // second little endian path table + write_little_endian_dword(0); // second little endian path table write_big_endian_dword(big_endian_path_table_sector); - write_big_endian_dword((DWORD) 0); // second big endian path table + write_big_endian_dword(0); // second big endian path table write_directory_record(&root, DOT_RECORD, FALSE);
- write_bytecounted_string(128, volume_label); // volume set identifier - write_bytecounted_string(128, PUBLISHER_ID); // publisher identifier - write_bytecounted_string(128, DATA_PREP_ID); // data preparer identifier - write_bytecounted_string(128, APP_ID); // application identifier - - write_bytecounted_string(37, ""); // copyright file identifier - write_bytecounted_string(37, ""); // abstract file identifier - write_bytecounted_string(37, ""); // bibliographic file identifier + write_bytecounted_string(128, volume_label, ' '); // volume set identifier + write_bytecounted_string(128, PUBLISHER_ID, ' '); // publisher identifier + write_bytecounted_string(128, DATA_PREP_ID, ' '); // data preparer identifier + write_bytecounted_string(128, APP_ID, ' '); // application identifier + + write_bytecounted_string(37, "", ' '); // copyright file identifier + write_bytecounted_string(37, "", ' '); // abstract file identifier + write_bytecounted_string(37, "", ' '); // bibliographic file identifier
write_string(timestring); // volume creation write_byte(0); @@ -1382,10 +1437,9 @@ // Boot Volume Descriptor if (eltorito) { - write_byte(0); + write_byte(0); // Boot record ID write_string("CD001\1"); - write_string("EL TORITO SPECIFICATION"); // identifier - write_block(9, 0); // padding + write_bytecounted_string(32, "EL TORITO SPECIFICATION", 0); // El-Torito identifier write_block(32, 0); // unused write_little_endian_dword(boot_catalog_sector); // pointer to boot catalog fill_sector(); @@ -1396,31 +1450,31 @@ { write_string("\2CD001\1"); write_byte(0); - write_bytecounted_string_as_big_endian_unicode(32, ""); // system identifier - write_bytecounted_string_as_big_endian_unicode(32, volume_label); // volume label + write_bytecounted_string_as_big_endian_unicode(32, "", ' '); // system identifier + write_bytecounted_string_as_big_endian_unicode(32, volume_label, ' '); // volume label
write_block(8, 0); write_both_endian_dword(total_sectors); write_string("%/E"); write_block(29, 0); - write_both_endian_word((WORD) 1); // volume set size - write_both_endian_word((WORD) 1); // volume sequence number - write_both_endian_word((WORD) 2048); // sector size + write_both_endian_word(1); // volume set size + write_both_endian_word(1); // volume sequence number + write_both_endian_word(2048); // sector size write_both_endian_dword(joliet_path_table_size); write_little_endian_dword(joliet_little_endian_path_table_sector); - write_little_endian_dword((DWORD) 0); // second little endian path table + write_little_endian_dword(0); // second little endian path table write_big_endian_dword(joliet_big_endian_path_table_sector); - write_big_endian_dword((DWORD) 0); // second big endian path table + write_big_endian_dword(0); // second big endian path table write_directory_record(&root, DOT_RECORD, TRUE);
- write_bytecounted_string_as_big_endian_unicode(128, volume_label); // volume set identifier - write_bytecounted_string_as_big_endian_unicode(128, PUBLISHER_ID); // publisher identifier - write_bytecounted_string_as_big_endian_unicode(128, DATA_PREP_ID); // data preparer identifier - write_bytecounted_string_as_big_endian_unicode(128, APP_ID); // application identifier - - write_bytecounted_string_as_big_endian_unicode(37, ""); // copyright file identifier - write_bytecounted_string_as_big_endian_unicode(37, ""); // abstract file identifier - write_bytecounted_string_as_big_endian_unicode(37, ""); // bibliographic file identifier + write_bytecounted_string_as_big_endian_unicode(128, volume_label, ' '); // volume set identifier + write_bytecounted_string_as_big_endian_unicode(128, PUBLISHER_ID, ' '); // publisher identifier + write_bytecounted_string_as_big_endian_unicode(128, DATA_PREP_ID, ' '); // data preparer identifier + write_bytecounted_string_as_big_endian_unicode(128, APP_ID, ' '); // application identifier + + write_bytecounted_string_as_big_endian_unicode(37, "", ' '); // copyright file identifier + write_bytecounted_string_as_big_endian_unicode(37, "", ' '); // abstract file identifier + write_bytecounted_string_as_big_endian_unicode(37, "", ' '); // bibliographic file identifier
write_string(timestring); // volume creation write_byte(0); @@ -1439,40 +1493,72 @@ write_string("\377CD001\1"); fill_sector();
- // Boot Catalog + // Boot Catalog and Images if (eltorito) { + PBOOT_HEADER header; + PBOOT_ENTRY entry; + + // Boot Catalog + boot_catalog_sector = cd.sector;
- // Validation entry - write_byte(1); - write_byte(0); // x86 boot code + // Validation entry header + write_byte(boot_validation_header.header_id); + write_byte(boot_validation_header.platform_id); write_little_endian_word(0); // reserved - write_string("ReactOS Foundation"); - write_block(6, 0); // padding + write_bytecounted_string(24, MANUFACTURER_ID, 0); // Manufacturer identifier write_little_endian_word(0x62E); // checksum // FIXME: This is hardcoded!! write_little_endian_word(0xAA55); // signature
- // default entry - write_byte(0x88); // bootable - write_byte(0); // no emulation - write_big_endian_word(0); // load segment = default (0x07c0) + // Default entry + write_byte(default_boot_entry.boot_id); + write_byte(default_boot_entry.boot_emu_type); + write_little_endian_word(default_boot_entry.load_segment); write_byte(0); // partition type write_byte(0); // unused - write_little_endian_word(boot_image_size); // sector count - write_little_endian_dword(boot_image_sector); // sector + write_little_endian_word(default_boot_entry.sector_count); + write_little_endian_dword(default_boot_entry.load_rba); + write_block(20, 0); // unused + + // Loop through each boot header + header = boot_header_list; + while (header) + { + write_byte(header->header_id); + write_byte(header->platform_id); + write_little_endian_word(header->num_entries); + write_block(28, 0); // Identifier string (unused) + + // Loop through each boot entry + entry = header->entry_list; + while (entry) + { + write_byte(entry->boot_id); + write_byte(entry->boot_emu_type); + write_little_endian_word(entry->load_segment); + write_byte(0); // partition type + write_byte(0); // unused + write_little_endian_word(entry->sector_count); + write_little_endian_dword(entry->load_rba); + write_block(20, 0); // Selection criteria (unused) + + entry = entry->next_entry; + } + + header = header->next_header; + }
fill_sector(); - } - - // Boot Image - if (eltorito) - { - boot_image_sector = cd.sector; - - file = fopen(bootimage, "rb"); + + + // Boot Images + + default_boot_entry.load_rba = cd.sector; + + file = fopen(default_boot_entry.bootimage, "rb"); if (file == NULL) - error_exit("Can't open %s\n", bootimage); + error_exit("Cannot open %s\n", default_boot_entry.bootimage); fseek(file, 0, SEEK_END); size = ftell(file); if (size == 0 || (size % 2048)) @@ -1480,13 +1566,50 @@ fclose(file); error_exit("Invalid boot image size (%lu bytes)\n", size); } - boot_image_size = size / 512; + // Sector count in 512 byte sectors and rounded up + default_boot_entry.sector_count = (size + 511) / 512; if (!write_from_file(file, size)) { fclose(file); - error_exit("Read error in file %s\n", bootimage); + error_exit("Read error in file %s\n", default_boot_entry.bootimage); } fclose(file); + + // Loop through each boot header + header = boot_header_list; + while (header) + { + // Loop through each boot entry + entry = header->entry_list; + while (entry) + { + entry->load_rba = cd.sector; + + file = fopen(entry->bootimage, "rb"); + if (file == NULL) + error_exit("Cannot open %s\n", entry->bootimage); + fseek(file, 0, SEEK_END); + size = ftell(file); + if (size == 0 || (size % 2048)) + { + fclose(file); + error_exit("Invalid boot image size (%lu bytes)\n", size); + } + // Sector count in 512 byte sectors and rounded up + entry->sector_count = (size + 511) / 512; + if (!write_from_file(file, size)) + { + fclose(file); + error_exit("Read error in file %s\n", entry->bootimage); + } + fclose(file); + + entry = entry->next_entry; + } + + header = header->next_header; + } + // fill_sector(); }
@@ -1495,7 +1618,7 @@ write_byte(1); write_byte(0); // number of sectors in extended attribute record write_little_endian_dword(root.sector); - write_little_endian_word((WORD) 1); + write_little_endian_word(1); write_byte(0); write_byte(0);
@@ -1524,7 +1647,7 @@ write_byte(1); write_byte(0); // number of sectors in extended attribute record write_big_endian_dword(root.sector); - write_big_endian_word((WORD) 1); + write_big_endian_word(1); write_byte(0); write_byte(0);
@@ -1549,7 +1672,7 @@ write_byte(1); write_byte(0); // number of sectors in extended attribute record write_little_endian_dword(root.joliet_sector); - write_little_endian_word((WORD) 1); + write_little_endian_word(1); write_byte(0); write_byte(0);
@@ -1573,7 +1696,7 @@ write_byte(1); write_byte(0); // number of sectors in extended attribute record write_big_endian_dword(root.joliet_sector); - write_big_endian_word((WORD) 1); + write_big_endian_word(1); write_byte(0); write_byte(0);
@@ -1659,7 +1782,7 @@ printf("Writing contents of %s\n", file_source); file = fopen(file_source, "rb"); if (file == NULL) - error_exit("Can't open %s\n", file_source); + error_exit("Cannot open %s\n", file_source); if (!write_from_file(file, size)) { fclose(file); @@ -1682,32 +1805,79 @@ "Copyright (C) Philip J. Erdelsky\n" "Copyright (C) 2003-2015 ReactOS Team\n" "\n\n" - "CDMAKE [-q] [-v] [-p] [-s N] [-m] [-b bootimage] [-j] source volume image\n" + "CDMAKE [-vN] [-p] [-s N] [-m] [-j] [-pN] [-eN] [-b bootimage]\n" + " [-bootdata:N#<defaultBootEntry>#<bootEntry1>#...#<bootEntryN>]\n" + " source volume image\n" "\n" - " source Specifications of base directory containing all files to\n" - " be written to CD-ROM image\n" - " volume Volume label\n" - " image Image file or device\n" - " -q Quiet mode - display nothing but error messages\n" - " -v Verbose mode - display file information as files are\n" - " scanned and written - overrides -p option\n" - " -p Show progress while writing\n" - " -s N Abort operation before beginning write if image will be\n" - " larger than N megabytes (i.e. 1024*1024*N bytes)\n" - " -m Accept punctuation marks other than underscores in\n" - " names and extensions\n" - " -b bootimage Create bootable ElTorito CD-ROM using 'no emulation' mode\n" - " -j Generate Joliet filename records\n"; + " -vN Verbosity level. Valid values for 'N' are:\n" + " 0: Quiet mode - display nothing but error messages.\n" + " 1: Normal mode (default).\n" + " 2: Verbose mode - display file information as files are\n" + " scanned and written. Overrides the -p option.\n" + " -p Show progress while writing.\n" + " -s N Abort operation before beginning write if image will be larger\n" + " than N megabytes (i.e. 1024*1024*N bytes).\n" + " -m Accept punctuation marks other than underscores in names and\n" + " extensions.\n" + " -j Generate Joliet filename records.\n" + "\n" + " -pN Boot platform ID in hex format (default: 00 for a BIOS system).\n" + " -eN Boot media emulation. Valid values for 'N' are:\n" + " 0 (or nothing): No emulation.\n" + " 1: 1.2Mb diskette.\n" + " 2: 1.44Mb diskette.\n" + " 3: 2.88Mb diskette.\n" + " 4: Hard disk.\n" + " -b bootimage Create a single-boot El-Torito image.\n" + " -bootdata: Create a multi-boot El-Torito image. This option cannot be\n" + " combined with the -b option.\n" + " Syntax:\n" + " -bootdata:N#<defaultBootEntry>#<bootEntry2>#...#<bootEntryN>\n" + " 'N': number of boot entries following.\n" + " defaultBootEntry: The default boot entry, needed in all cases.\n" + " Used by BIOSes which do not support additional boot entries.\n" + " bootEntryX: Additional boot entries.\n" + " - Do not use spaces.\n" + " - Each multi-boot entry must be delimited with a hash symbol (#).\n" + " - Each option for a boot entry must be delimited with a comma (,).\n" + " - Each boot entry must specify the platform ID.\n" + "\n" + " source Specifications of base directory containing all files to be\n" + " written to CD-ROM image.\n" + " volume Volume label.\n" + " image Image file or device.\n";
/*----------------------------------------------------------------------------- Program execution starts here. -----------------------------------------------------------------------------*/
+char* strtok_s(char *str, const char *delim, char **ctx) +{ + if (delim == NULL || ctx == NULL || (str == NULL && *ctx == NULL)) + { + return NULL; + } + + if (!str) + str = *ctx; + + while (*str && strchr(delim, *str)) + str++; + if (!*str) + return NULL; + + *ctx = str + 1; + while (**ctx && !strchr(delim, **ctx)) + (*ctx)++; + if (**ctx) + *(*ctx)++ = '\0'; + + return str; +} + int main(int argc, char **argv) { time_t timestamp = time(NULL); - BOOL q_option = FALSE; - BOOL v_option = FALSE; int i; char *t;
@@ -1717,7 +1887,7 @@ return 1; }
- // initialize root directory + // Initialize root directory
cd.buffer = malloc(BUFFER_SIZE); if (cd.buffer == NULL) @@ -1728,27 +1898,57 @@ root.flags = DIRECTORY_FLAG; convert_date_and_time(&root.date_and_time, ×tamp);
- // initialize CD-ROM write buffer + // Initialize CD-ROM write buffer
cd.file = NULL; cd.filespecs[0] = 0;
- // initialize parameters + // Initialize parameters
verbosity = NORMAL; + show_progress = FALSE; size_limit = 0; - show_progress = FALSE; accept_punctuation_marks = FALSE; source[0] = 0; volume_label[0] = 0;
- eltorito = FALSE; - - // scan command line arguments + // Initialize boot information + eltorito = FALSE; + multi_boot = FALSE; + boot_validation_header.header_id = 1; // Validation header ID + boot_validation_header.platform_id = 0; // x86/64 BIOS system + default_boot_entry.boot_id = 0x88; // Bootable entry + default_boot_entry.boot_emu_type = 0; // No emulation + default_boot_entry.load_segment = 0; // 0 --> use default 0x07C0 + default_boot_entry.sector_count = 0; + default_boot_entry.load_rba = 0; + default_boot_entry.bootimage[0] = '\0'; + boot_header_list = NULL; + + // Scan command line arguments
for (i = 1; i < argc; i++) { - if (memcmp(argv[i], "-s", 2) == 0) + if (strncmp(argv[i], "-v", 2) == 0) + { + t = argv[i] + 2; + if (*t == 0) // Normal verbosity level. + verbosity = NORMAL; + else // Verbosity level in decimal + verbosity = strtoul(t, NULL, 10); + + // Check for validity + if (verbosity > VERBOSE) + verbosity = NORMAL; + + // Disable by default, unless we are in normal verbosity level. + // If progress is still wanted, use '-p'. + if (verbosity == QUIET || verbosity == VERBOSE) + show_progress = FALSE; + } + else if (strcmp(argv[i], "-p") == 0) + show_progress = TRUE; + else if (strncmp(argv[i], "-s", 2) == 0) { t = argv[i] + 2; if (*t == 0) @@ -1758,26 +1958,254 @@ else error_exit("Missing size limit parameter"); } + // size_limit = strtoul(t, NULL, 10); while (isdigit(*t)) size_limit = size_limit * 10 + *t++ - '0'; if (size_limit < 1 || size_limit > 800) error_exit("Invalid size limit"); size_limit <<= 9; // convert megabyte to sector count } - else if (strcmp(argv[i], "-q") == 0) - q_option = TRUE; - else if (strcmp(argv[i], "-v") == 0) - v_option = TRUE; - else if (strcmp(argv[i], "-p") == 0) - show_progress = TRUE; else if (strcmp(argv[i], "-m") == 0) accept_punctuation_marks = TRUE; else if (strcmp(argv[i], "-j") == 0) joliet = TRUE; + else if (strncmp(argv[i], "-e", 2) == 0) + { + // Check whether the multi-boot option '-bootdata:' was already set. + // If so, print an error and bail out. + if (eltorito && multi_boot) + error_exit("Single-boot and multi-boot entries cannot be combined"); + + eltorito = TRUE; + multi_boot = FALSE; + + t = argv[i] + 2; + if (*t == 0) // No emulation + default_boot_entry.boot_emu_type = 0; + else // ID in decimal + default_boot_entry.boot_emu_type = (BYTE)strtoul(t, NULL, 10); + } + else if (strncmp(argv[i], "-p", 2) == 0) + { + // Check whether the multi-boot option '-bootdata:' was already set. + // If so, print an error and bail out. + if (eltorito && multi_boot) + error_exit("Single-boot and multi-boot entries cannot be combined"); + + eltorito = TRUE; + multi_boot = FALSE; + + // Platform ID in hexadecimal + boot_validation_header.platform_id = (BYTE)strtoul(argv[i] + 2, NULL, 16); + } else if (strcmp(argv[i], "-b") == 0) { - strcpy(bootimage, argv[++i]); - eltorito = TRUE; + // Check whether the multi-boot option '-bootdata:' was already set. + // If so, print an error and bail out. + if (eltorito && multi_boot) + error_exit("Single-boot and multi-boot entries cannot be combined"); + + eltorito = TRUE; + multi_boot = FALSE; + + strncpy(default_boot_entry.bootimage, argv[++i], sizeof(default_boot_entry.bootimage)); + default_boot_entry.bootimage[sizeof(default_boot_entry.bootimage)-1] = '\0'; + } + else if (strncmp(argv[i], "-bootdata:", sizeof("-bootdata:") - 1) == 0) + { + char *bootdata, *entry_ctx, *option_ctx; + DWORD num_boot_entries = 0; + + BOOL default_entry = TRUE; // Start by setting the default boot entry + PBOOT_HEADER boot_header = NULL; // Current boot header + PBOOT_ENTRY boot_entry = NULL; // The last boot entry in the current boot header + BYTE platform_id, old_platform_id = 0; + BYTE boot_emu_type; + WORD load_segment; + char bootimage[512]; + + // Check whether the single-boot option '-b' was already set. + // If so, print an error and bail out. + if (eltorito && !multi_boot) + error_exit("Single-boot and multi-boot entries cannot be combined"); + + t = argv[i] + (sizeof("-bootdata:") - 1); + bootdata = strdup(t); + if (bootdata == NULL) + error_exit("Insufficient memory"); + + eltorito = TRUE; + multi_boot = TRUE; + + // FIXME: Paths with '#' or ',' or ' ' inside are not yet supported!! + + // Start parsing... + t = strtok_s(bootdata, "#", &entry_ctx); + if (t == NULL) + { + free(bootdata); + error_exit("Malformed bootdata command"); + } + + num_boot_entries = strtoul(t, NULL, 10); + + while (num_boot_entries--) + { + // Reset to default values + platform_id = 0; // x86/64 BIOS system + boot_emu_type = 0; // No emulation + load_segment = 0; // 0 --> use default 0x07C0 + bootimage[0] = '\0'; + + t = strtok_s(NULL, "#", &entry_ctx); + if (t == NULL) + { + free(bootdata); + error_exit("Malformed bootdata command"); + } + + t = strtok_s(t, ",", &option_ctx); + while (t != NULL) + { + switch (*t++) + { + case 'b': // Boot sector file + { + char *q; + + // Searches for any of the valid separators: + // '#' starts a new boot entry; + // ',' starts a new boot option; + // ' ' finishes the bootdata command. + q = strpbrk(t, "#, "); + if (!q) q = t + strlen(t); + strncpy(bootimage, t, q - t + 1); + break; + } + + case 'p': // Platform ID + { + // Platform ID in hexadecimal + platform_id = (BYTE)strtoul(t, NULL, 16); + break; + } + + case 'e': // No floppy-disk emulation + { + if (*t == 0) // No emulation + boot_emu_type = 0; + else // ID in decimal + boot_emu_type = (BYTE)strtoul(t, NULL, 10); + + break; + } + + case 't': // Loading segment + { + if (*t == 0) // Not specified --> use default 0x07C0 + load_segment = 0; + else // Segment in hexadecimal + load_segment = (BYTE)strtoul(t, NULL, 16); + + break; + } + + default: + free(bootdata); + error_exit("Malformed bootdata command"); + } + + t = strtok_s(NULL, ",", &option_ctx); + } + + // Create a new entry and possibly a boot header + if (default_entry) + { + // Initialize the default boot entry and header + + boot_validation_header.header_id = 1; // Validation header ID + boot_validation_header.platform_id = platform_id; + default_boot_entry.boot_id = 0x88; // Bootable entry + default_boot_entry.boot_emu_type = boot_emu_type; + default_boot_entry.load_segment = load_segment; + + strncpy(default_boot_entry.bootimage, bootimage, sizeof(default_boot_entry.bootimage)); + default_boot_entry.bootimage[sizeof(default_boot_entry.bootimage)-1] = '\0'; + + // Default entry is now initialized. + default_entry = FALSE; + } + else + { + // Initialize a new boot entry + PBOOT_ENTRY old_boot_entry = boot_entry; + + boot_entry = calloc(1, sizeof(*boot_entry)); + if (boot_entry == NULL) + error_exit("Insufficient memory"); + // boot_entry->next_entry = NULL; + + boot_entry->boot_id = 0x88; // Bootable entry + boot_entry->boot_emu_type = boot_emu_type; + boot_entry->load_segment = load_segment; + + strncpy(boot_entry->bootimage, bootimage, sizeof(boot_entry->bootimage)); + boot_entry->bootimage[sizeof(boot_entry->bootimage)-1] = '\0'; + + // Create a new boot header if we don't have one yet + if (boot_header == NULL) + { + boot_header = calloc(1, sizeof(*boot_header)); + if (boot_header == NULL) + error_exit("Insufficient memory"); + + boot_header->header_id = 0x91; // So far this is the last boot header + boot_header->platform_id = platform_id; + // boot_header->next_header = NULL; + // boot_header->num_entries = 0; + // boot_header->entry_list = NULL; + + old_boot_entry = NULL; + old_platform_id = platform_id; + + boot_header_list = boot_header; + } + else + { + // Create a new boot header if we change the platform ID + if (old_platform_id != platform_id) + { + PBOOT_HEADER prev_boot_header = boot_header; + + boot_header = calloc(1, sizeof(*boot_header)); + if (boot_header == NULL) + error_exit("Insufficient memory"); + + boot_header->header_id = 0x91; // So far this is the last boot header + boot_header->platform_id = platform_id; + // boot_header->next_header = NULL; + // boot_header->num_entries = 0; + // boot_header->entry_list = NULL; + + old_boot_entry = NULL; + old_platform_id = platform_id; + + // Link into the header list + prev_boot_header->header_id = 0x90; // The previous boot header was not the last one + prev_boot_header->next_header = boot_header; + } + } + + // Add the entry into the header + ++boot_header->num_entries; + if (old_boot_entry == NULL) + boot_header->entry_list = boot_entry; + else + old_boot_entry->next_entry = boot_entry; + } + } + + free(bootdata); } else if (i + 2 < argc) { @@ -1788,16 +2216,7 @@ else error_exit("Missing command line argument"); } - if (v_option) - { - show_progress = FALSE; - verbosity = VERBOSE; - } - else if (q_option) - { - verbosity = QUIET; - show_progress = FALSE; - } + if (source[0] == 0) error_exit("Missing source directory"); if (volume_label[0] == 0) @@ -1820,13 +2239,13 @@ } else { - char *trimmedline, *targetname, *srcname, *eq; + char *trimmedline, *targetname, *srcname, *eq, *normdir; char lineread[1024];
FILE *f = fopen(source+1, "r"); if (!f) { - error_exit("Can't open cd description %s\n", source+1); + error_exit("Cannot open cd description %s\n", source+1); } while (fgets(lineread, sizeof(lineread), f)) { @@ -1835,7 +2254,6 @@ eq = strchr(trimmedline, '='); if (!eq) { - char *normdir; /* Treat this as a directory name */ targetname = trimmedline; normdir = strdup(targetname); @@ -1852,12 +2270,12 @@ if (_access(srcname, R_OK) == 0) dir_hash_add_file(&specified_files, srcname, targetname); else - error_exit("can't access file '%s' (target %s)\n", srcname, targetname); + error_exit("Cannot access file '%s' (target %s)\n", srcname, targetname); #else if (access(srcname, R_OK) == 0) dir_hash_add_file(&specified_files, srcname, targetname); else - error_exit("can't access file '%s' (target %s)\n", srcname, targetname); + error_exit("Cannot access file '%s' (target %s)\n", srcname, targetname); #endif } } @@ -1877,7 +2295,7 @@ cd.file = NULL; cd.sector = 0; cd.offset = 0; - cd.count = 0; + cd.count = 0;
// make non-writing pass over directory structure to obtain the proper // sector numbers and offsets and to determine the size of the image @@ -1909,10 +2327,10 @@
cd.file = fopen(cd.filespecs, "w+b"); if (cd.file == NULL) - error_exit("Can't open image file %s", cd.filespecs); + error_exit("Cannot open image file %s", cd.filespecs); cd.sector = 0; cd.offset = 0; - cd.count = 0; + cd.count = 0;
// make writing pass over directory structure
Modified: trunk/reactos/tools/cdmake/config.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/tools/cdmake/config.h?rev=6... ============================================================================== --- trunk/reactos/tools/cdmake/config.h [iso-8859-1] (original) +++ trunk/reactos/tools/cdmake/config.h [iso-8859-1] Wed Sep 9 02:11:49 2015 @@ -9,6 +9,7 @@ #define DIR_SEPARATOR_STRING "\" #endif
+#define MANUFACTURER_ID "ReactOS Foundation" #define PUBLISHER_ID "ReactOS Foundation" #define DATA_PREP_ID "ReactOS Foundation" #define APP_ID "CDMAKE CD-ROM Premastering Utility"
Modified: trunk/reactos/tools/cdmake/dirhash.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/tools/cdmake/dirhash.c?rev=... ============================================================================== --- trunk/reactos/tools/cdmake/dirhash.c [iso-8859-1] (original) +++ trunk/reactos/tools/cdmake/dirhash.c [iso-8859-1] Wed Sep 9 02:11:49 2015 @@ -1,3 +1,10 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS CD-ROM Maker + * FILE: tools/cdmake/dirhash.c + * PURPOSE: CD-ROM Premastering Utility - Directory names hashing + * PROGRAMMERS: Art Yerkes + */ #include <string.h> #include <stdlib.h> #include <ctype.h>
Modified: trunk/reactos/tools/cdmake/dirhash.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/tools/cdmake/dirhash.h?rev=... ============================================================================== --- trunk/reactos/tools/cdmake/dirhash.h [iso-8859-1] (original) +++ trunk/reactos/tools/cdmake/dirhash.h [iso-8859-1] Wed Sep 9 02:11:49 2015 @@ -1,3 +1,10 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS CD-ROM Maker + * FILE: tools/cdmake/dirhash.h + * PURPOSE: CD-ROM Premastering Utility - Directory names hashing + * PROGRAMMERS: Art Yerkes + */ #ifndef _DIRHASH_H_ #define _DIRHASH_H_