diff --git a/doc/boot_sectors.txt b/doc/boot_sectors.txt index 381f5d0..c9c0d33 100644 --- a/doc/boot_sectors.txt +++ b/doc/boot_sectors.txt @@ -1104,7 +1104,44 @@ Byte Range | Value | Meaning ------------------------------------------------------------------------------ ->>> ??? DEC Alpha + DEC Alpha SRM boot sector + for Alpha architecture + +Sources: + http://www.tldp.org/HOWTO/text/SRM-HOWTO + SRM Firmware Howto - Rich Payne, and David Huggins-Daines + cdrkit-1.1.10/genisoimage/boot-alpha.c + by Steve McIntyre + who states "Heavily inspired by isomarkboot by David Mosberger in 1996" + mail conversations with Helge Deller + +The SRM firmware expects a Secondary Bootstrap Loader program, which usually +is a data file of the ISO filesystem. This loader is announced by size and +block address in the first 512 bytes of the System Area. +SRM accepts the boot sector and executes the loader if the checksum matches. + +All numbers are recorded as unsigned 64 bit little endian. + +Boot sector components: + +Byte Range | Value | Meaning +---------- | ---------- | ---------------------------------------------------- + 0 - ? | boot_string| genisoimage writes + | | "Linux/Alpha aboot for ISO filesystem." + | | with terminating zero byte. + | | + ? - 479 | 0 | Unused / undefined. + | | + 480 - 487 | length | Size of boot loader file in units of 512 bytes. + | | + 488 - 495 | address | LBA of the boot loader file in units of 512 bytes. + | | + 496 - 503 | flag | "Always 0" + | | + 504 - 511 | checksum | Sum of 64 bit words 0 to 63 (bytes 0 to 503). + | | +---------- | ---------- | ---------------------------------------------------- + ------------------------------------------------------------------------------ diff --git a/libisofs/ecma119.c b/libisofs/ecma119.c index f3e5e60..aa519df 100644 --- a/libisofs/ecma119.c +++ b/libisofs/ecma119.c @@ -637,6 +637,7 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent) /* initialize the ce_block, it might be needed */ info.ce_block = dir->info.dir->block + DIV_UP(dir->info.dir->len, BLOCK_SIZE); + info.ce_susp_fields = NULL; } /* write the "." and ".." entries first */ diff --git a/libisofs/fs_image.c b/libisofs/fs_image.c index 45c4089..cf15ae4 100644 --- a/libisofs/fs_image.c +++ b/libisofs/fs_image.c @@ -4631,9 +4631,58 @@ int iso_analyze_hppa(IsoImage *image, IsoDataSource *src, int flag) /* HP-PA PALO boot sector version 4 or 5 for HP PA-RISC */ sai->system_area_options = (sai->hppa_hdrversion << 2); - return ret; + return 1; } +static +int iso_analyze_alpha_boot(IsoImage *image, IsoDataSource *src, int flag) +{ + int ret = 0, i, section_count; + char *sad; + uint8_t *usad; + struct iso_imported_sys_area *sai; + IsoNode *node; + IsoFile *file; + uint64_t checksum_found, checksum_should = 0, size; + struct iso_file_section *sections = NULL; + + sai = image->imported_sa_info; + sad = image->system_area_data; + usad = (uint8_t *) sad; + + checksum_found = iso_read_lsb64(usad + 504); + for (i = 0; i < 63; i++) + checksum_should += iso_read_lsb64(usad + 8 * i); + if (checksum_found != checksum_should) + return 0; + sai->alpha_boot_image = NULL; + sai->alpha_boot_image_size = (uint64_t) iso_read_lsb64(usad + 480); + sai->alpha_boot_image_adr = (uint64_t) iso_read_lsb64(usad + 488); + ret = iso_tree_get_node_of_block(image, NULL, + (uint32_t) (sai->alpha_boot_image_adr / 4), + &node, NULL, 0); + if (ret > 0) { + if (iso_node_get_type(node) != LIBISO_FILE) + return 0; + file = (IsoFile *) node; + ret = iso_file_get_old_image_sections(file, §ion_count, + §ions, 0); + if (ret > 0) { + size = sections[0].size / 512 + !!(sections[0].size % 512); + free(sections); + if (size != sai->alpha_boot_image_size) + return 0; + } + sai->alpha_boot_image = iso_tree_get_node_path(node); + } else if (strncmp(sad, "Linux/Alpha aboot for ISO filesystem.", 37) != 0 + || sad[37] != 0) { + return 0; /* Want to see either boot file or genisoimage string */ + } + sai->system_area_options = (6 << 2); + return 1; +} + + struct iso_impsysa_result { char *buf; int byte_count; @@ -4867,6 +4916,8 @@ int iso_impsysa_report(IsoImage *image, struct iso_impsysa_result *target, strcat(msg, " SUN-SPARC-Disk-Label"); } else if (sa_type == 4 || sa_type == 5) { sprintf(msg + strlen(msg), " HP-PA-PALO"); + } else if (sa_type == 6) { + sprintf(msg + strlen(msg), " DEC-Alpha"); } else { sprintf(msg + strlen(msg), " unkown-system-area-type-%d", sa_type); } @@ -4911,6 +4962,17 @@ int iso_impsysa_report(IsoImage *image, struct iso_impsysa_result *target, iso_impsysa_report_text(target, msg, sai->hppa_bootloader != NULL ? sai->hppa_bootloader : "(not found in ISO)", 0); + } else if (sa_type == 6) { + sprintf(msg, "DEC Alpha ldr size : %.f", + (double) sai->alpha_boot_image_size); + iso_impsysa_line(target, msg); + sprintf(msg, "DEC Alpha ldr adr : %.f", + (double) sai->alpha_boot_image_adr); + iso_impsysa_line(target, msg); + if (sai->alpha_boot_image != NULL) { + sprintf(msg, "DEC Alpha ldr path : %s", sai->alpha_boot_image); + iso_impsysa_line(target, msg); + } } if (sai->mbr_req_count > 0) { sprintf(msg, "MBR heads per cyl : %d", sai->partition_heads_per_cyl); @@ -5310,6 +5372,7 @@ int iso_image_report_boot_eqp(IsoImage *image, int what, ISO_SYSAREA_REPORT_DOC_MIPS , ISO_SYSAREA_REPORT_DOC_SUN , ISO_SYSAREA_REPORT_DOC_HPPA , + ISO_SYSAREA_REPORT_DOC_ALPHA , "@END_OF_DOC@" }; static char *eltorito_doc[] = { ISO_ELTORITO_REPORT_DOC , "@END_OF_DOC@" }; @@ -5491,6 +5554,12 @@ int iso_analyze_system_area(IsoImage *image, IsoDataSource *src, ret = iso_analyze_hppa(image, src, 0); if (ret < 0) goto ex; + /* DEC Alpha has checksum bytes where MBR has its magic number */ + if (ret == 0) { + ret = iso_analyze_alpha_boot(image, src, 0); + if (ret < 0) + goto ex; + } } ret = iso_record_meta_struct_blocks(image, src, 0); if (ret < 0) diff --git a/libisofs/image.c b/libisofs/image.c index 4eae955..30ec5b2 100644 --- a/libisofs/image.c +++ b/libisofs/image.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2007 Vreixo Formoso - * Copyright (c) 2009 - 2014 Thomas Schmitt + * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -51,6 +51,8 @@ int iso_imported_sa_new(struct iso_imported_sys_area **boots, int flag) b->hppa_kernel_64 = NULL; b->hppa_ramdisk = NULL; + b->alpha_boot_image = NULL; + *boots = b; return 1; } @@ -107,6 +109,7 @@ int iso_imported_sa_unref(struct iso_imported_sys_area **boots, int flag) LIBISO_FREE_MEM(b->hppa_kernel_32); LIBISO_FREE_MEM(b->hppa_kernel_64); LIBISO_FREE_MEM(b->hppa_ramdisk); + LIBISO_FREE_MEM(b->alpha_boot_image); LIBISO_FREE_MEM(b); *boots = NULL; return 1; @@ -177,10 +180,11 @@ int iso_image_new(const char *name, IsoImage **image) img->mips_boot_file_paths[i] = NULL; img->sparc_core_node = NULL; img->hppa_cmdline= NULL; - img->hppa_bootloader= NULL; - img->hppa_kernel_32= NULL; - img->hppa_kernel_64= NULL; - img->hppa_ramdisk= NULL; + img->hppa_bootloader = NULL; + img->hppa_kernel_32 = NULL; + img->hppa_kernel_64 = NULL; + img->hppa_ramdisk = NULL; + img->alpha_boot_image = NULL; img->builder_ignore_acl = 1; img->builder_ignore_ea = 1; img->inode_counter = 0; @@ -239,6 +243,8 @@ void iso_image_unref(IsoImage *image) if (image->sparc_core_node != NULL) iso_node_unref((IsoNode *) image->sparc_core_node); iso_image_set_hppa_palo(image, NULL, NULL, NULL, NULL, NULL, 1); + if (image->alpha_boot_image != NULL) + free(image->alpha_boot_image); free(image->volset_id); free(image->volume_id); free(image->publisher_id); @@ -969,9 +975,9 @@ int iso_image_get_sparc_core(IsoImage *img, IsoFile **sparc_core, int flag) Else only the non-NULL parameters of this call have an effect. */ static int hppa_palo_set_path(IsoImage *img, char *path, char **target, - int flag) + char *what, int flag) { - int ret; + int ret, err; IsoNode *node; IsoFile *file; @@ -986,13 +992,16 @@ static int hppa_palo_set_path(IsoImage *img, char *path, char **target, return ret; if (ret == 0) { iso_msg_submit(img->id, ISO_BOOT_FILE_MISSING, 0, - "Cannot find in ISO image: HP-PA file '%s'", path); + "Cannot find in ISO image: %s file '%s'", what, path); return ISO_BOOT_FILE_MISSING; } if (iso_node_get_type(node) != LIBISO_FILE) { - iso_msg_submit(img->id, ISO_HPPA_PALO_NOTREG, 0, - "HP-PA PALO file is not a data file: '%s'", path); - return ISO_HPPA_PALO_NOTREG; + err = ISO_HPPA_PALO_NOTREG; + if (strncmp(what, "DEC Alpha", 9) == 0) + err = ISO_ALPHA_BOOT_NOTREG; + iso_msg_submit(img->id, err, 0, + "%s file is not a data file: '%s'", what, path); + return err; } file = (IsoFile *) node; if (!(file->explicit_weight || file->from_old_session)) @@ -1012,21 +1021,25 @@ int iso_image_set_hppa_palo(IsoImage *img, char *cmdline, char *bootloader, int flag) { int ret; + static char *what = "HP-PA PALO"; if (cmdline != NULL || (flag & 1)) if (iso_clone_mgtd_mem(cmdline, &(img->hppa_cmdline), 0) < 0) return ISO_OUT_OF_MEM; - ret = hppa_palo_set_path(img, bootloader, &(img->hppa_bootloader), + ret = hppa_palo_set_path(img, bootloader, &(img->hppa_bootloader), what, flag & 1); if (ret < 0) return ret; - ret = hppa_palo_set_path(img, kernel_32, &(img->hppa_kernel_32), flag & 1); + ret = hppa_palo_set_path(img, kernel_32, &(img->hppa_kernel_32), what, + flag & 1); if (ret < 0) return ret; - ret = hppa_palo_set_path(img, kernel_64, &(img->hppa_kernel_64), flag & 1); + ret = hppa_palo_set_path(img, kernel_64, &(img->hppa_kernel_64), what, + flag & 1); if (ret < 0) return ret; - ret = hppa_palo_set_path(img, ramdisk, &(img->hppa_ramdisk), flag & 1); + ret = hppa_palo_set_path(img, ramdisk, &(img->hppa_ramdisk), what, + flag & 1); if (ret < 0) return ret; return ISO_SUCCESS; @@ -1046,3 +1059,24 @@ int iso_image_get_hppa_palo(IsoImage *img, char **cmdline, char **bootloader, } +/* API */ +int iso_image_set_alpha_boot(IsoImage *img, char *boot_loader_path, int flag) +{ + int ret; + + ret = hppa_palo_set_path(img, boot_loader_path, &(img->alpha_boot_image), + "DEC Alpha Bootloader", 1); + if (ret < 0) + return ret; + return ISO_SUCCESS; +} + + +/* API */ +int iso_image_get_alpha_boot(IsoImage *img, char **boot_loader_path) +{ + *boot_loader_path = img->alpha_boot_image; + return ISO_SUCCESS; +} + + diff --git a/libisofs/image.h b/libisofs/image.h index d7bd113..96977e1 100644 --- a/libisofs/image.h +++ b/libisofs/image.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2007 Vreixo Formoso - * Copyright (c) 2009 - 2014 Thomas Schmitt + * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -88,6 +88,9 @@ struct Iso_Image char *hppa_kernel_64; char *hppa_ramdisk; + /* Absolute DEC Alpha boot image path in the ISO image */ + char *alpha_boot_image; + /* image identifier, for message origin identifier */ int id; @@ -96,7 +99,7 @@ struct Iso_Image */ IsoFilesystem *fs; - /* + /** * Default builder to use when adding files to the image tree. */ IsoNodeBuilder *builder; @@ -385,6 +388,10 @@ struct iso_imported_sys_area { char *hppa_ramdisk; char *hppa_bootloader; + uint64_t alpha_boot_image_size; + uint64_t alpha_boot_image_adr; + char *alpha_boot_image; + /* Some block addresses of active and first session: PVD, L Pathtable, Opt L, M Pathtable, Opt M, root directory */ diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 1db3448..85e63fb 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -2203,6 +2203,9 @@ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size); * lib/common.h is defined as 5. * Submit all five parameters of iso_image_set_hppa_palo(): * cmdline, bootloader, kernel_32, kernel_64, ramdisk + * 6= DEC Alpha SRM boot sector + * @since 1.4.0 + * Submit bootloader path in ISO by iso_image_set_alpha_boot(). * bit8-9= Only with System area type 0 = MBR * @since 1.0.4 * Cylinder alignment mode eventually pads the image to make it @@ -2493,7 +2496,8 @@ int iso_write_opts_set_efi_bootp(IsoWriteOpts *opts, char *image_path, * Linux Native Partition = 0x83. See fdisk command L. * This parameter is ignored with SUN Disk Label. * @param flag - * Reserved for future usage, set to 0. + * bit0= The path may contain instructions for the interval reader + * All other bits are reserved for future usage. Set them to 0. * @return * ISO_SUCCESS or error * @@ -3729,7 +3733,7 @@ int iso_image_get_system_area(IsoImage *img, char data[32768], " human readable interpretation of system area options and other info", \ " The words are from the set:", \ " { MBR, CHRP, PReP, GPT, APM, MIPS-Big-Endian, MIPS-Little-Endian,", \ -" SUN-SPARC-Disk-Label, HP-PA-PALO,", \ +" SUN-SPARC-Disk-Label, HP-PA-PALO, DEC-Alpha, ", \ " protective-msdos-label, isohybrid, grub2-mbr,", \ " cyl-align-{auto,on,off,all}, not-recognized, }", \ " The acronyms indicate boot data for particular hardware/firmware.", \ @@ -3916,6 +3920,16 @@ int iso_image_get_system_area(IsoImage *img, char data[32768], " HP-PA bootloader : decimal decimal path", \ " tells the same for the bootloader file.", \ "" +#define ISO_SYSAREA_REPORT_DOC_ALPHA \ +"If a DEC Alpha SRM boot sector is present:", \ +" DEC Alpha ldr size : decimal", \ +" tells the number of 512-byte blocks in DEC Alpha Secondary Bootstrap" \ +" Loader file.", \ +" DEC Alpha ldr adr : decimal", \ +" tells the start of the loader file in units of 512-byte blocks.", \ +" DEC Alpha ldr path : path", \ +" tells the path of a file in the ISO image which starts at the loader", \ +" start address." /** * Obtain an array of texts describing the detected properties of the @@ -4214,6 +4228,42 @@ int iso_image_set_hppa_palo(IsoImage *img, char *cmdline, char *bootloader, int iso_image_get_hppa_palo(IsoImage *img, char **cmdline, char **bootloader, char **kernel_32, char **kernel_64, char **ramdisk); + +/** + * Submit the path of the DEC Alpha Secondary Bootstrap Loader file. + * The path must lead to an already existing data file in the ISO image + * which stays with this path until image production. + * This setting has an effect only if system area type is set to 6 + * with iso_write_opts_set_system_area(). + * + * @param img + * The image to be manipulated. + * @param boot_loader_path + * Absolute path of a data file in the ISO image. + * Submit NULL to free this image property. + * @param flag + * Bitfield for control purposes. Unused yet. Submit 0. + * @return + * 1 is success , <0 means error + * @since 1.4.0 + */ +int iso_image_set_alpha_boot(IsoImage *img, char *boot_loader_path, int flag); + +/** + * Inquire the path submitted by iso_image_set_alpha_boot() + * Do not free() the returned pointer. + * + * @param img + * The image to be inquired. + * @param cmdline + * Will return the path. NULL if none is currently submitted. + * @return + * 1 is success , <0 means error + * @since 1.4.0 + */ +int iso_image_get_alpha_boot(IsoImage *img, char **boot_loader_path); + + /** * Increments the reference counting of the given node. * @@ -8110,6 +8160,9 @@ int iso_conv_name_chars(IsoWriteOpts *opts, char *name, size_t name_len, /** Unrecognized inquiry for system area property (FAILURE, HIGH, -404) */ #define ISO_INQ_SYSAREA_PROP 0xE830FE6C +/** DEC Alpha Boot Loader file is not a data file (FAILURE, HIGH, -405) */ +#define ISO_ALPHA_BOOT_NOTREG 0xE830FE6A + /* Internal developer note: Place new error codes directly above this comment. diff --git a/libisofs/libisofs.ver b/libisofs/libisofs.ver index 85bd801..0a97969 100644 --- a/libisofs/libisofs.ver +++ b/libisofs/libisofs.ver @@ -90,6 +90,7 @@ iso_image_fs_get_volume_id; iso_image_generator_is_running; iso_image_get_abstract_file_id; iso_image_get_all_boot_imgs; +iso_image_get_alpha_boot; iso_image_get_app_use; iso_image_get_application_id; iso_image_get_attached_data; @@ -120,6 +121,7 @@ iso_image_remove_boot_image; iso_image_report_el_torito; iso_image_report_system_area; iso_image_set_abstract_file_id; +iso_image_set_alpha_boot; iso_image_set_app_use; iso_image_set_application_id; iso_image_set_biblio_file_id; diff --git a/libisofs/messages.c b/libisofs/messages.c index 993d8aa..3cb4e8f 100644 --- a/libisofs/messages.c +++ b/libisofs/messages.c @@ -519,6 +519,8 @@ const char *iso_error_to_msg(int errcode) return "Problems encountered during inspection of System Area"; case ISO_INQ_SYSAREA_PROP: return "Unrecognized inquiry for system area property"; + case ISO_ALPHA_BOOT_NOTREG: + return "DEC Alpha Boot Loader file is not a data file"; default: return "Unknown error"; } diff --git a/libisofs/system_area.c b/libisofs/system_area.c index f158d88..90f655c 100644 --- a/libisofs/system_area.c +++ b/libisofs/system_area.c @@ -913,6 +913,45 @@ static int make_hppa_palo_sector(Ecma119Image *t, uint8_t *buf, int hdrversion, } +/** + * Write DEC Alpha boot sector. See doc/boot_sectors.txt + * + * learned from cdrkit-1.1.10/genisoimage/boot-alpha.c + * by Steve McIntyre + * who states "Heavily inspired by isomarkboot by David Mosberger in 1996" + * + */ +static int make_dec_alpha_sector(Ecma119Image *t, uint8_t *buf, int flag) +{ + int ret, i; + IsoImage *img; + IsoNode *iso_node; + Ecma119Node *ecma_node; + uint64_t size, lba, checksum = 0; + + img = t->image; + if (img->alpha_boot_image == NULL) + return ISO_SUCCESS; + ret = boot_nodes_from_iso_path(t, img->alpha_boot_image, + &iso_node, &ecma_node, "DEC Alpha boot file", 0); + if (ret < 0) + return ret; + memset(buf, 0, 512); + strcpy((char *) buf, "Linux/Alpha aboot for ISO filesystem."); + lba = ecma_node->info.file->sections[0].block * 4; + size = ecma_node->info.file->sections[0].size / 512 + + !!(ecma_node->info.file->sections[0].size % 512); + iso_lsb(buf + 480, size & 0xffffffff, 4); + iso_lsb(buf + 484, (size >> 32) & 0xffffffff, 4); + iso_lsb(buf + 488, lba & 0xffffffff, 4); + iso_lsb(buf + 492, (lba >> 32) & 0xffffffff, 4); + for (i = 0; i < 63; i++) + checksum += iso_read_lsb64(buf + 8 * i); + iso_lsb(buf + 504, checksum & 0xffffffff, 4); + iso_lsb(buf + 508, (checksum >> 32) & 0xffffffff, 4); + return ISO_SUCCESS; +} + /* Convenience frontend for iso_register_apm_entry(). name and type are 0-terminated strings. */ @@ -1778,6 +1817,10 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf) ret = make_hppa_palo_sector(t, buf, sa_type, 0); if (ret != ISO_SUCCESS) return ret; + } else if (sa_type == 6) { + ret = make_dec_alpha_sector(t, buf, 0); + if (ret != ISO_SUCCESS) + return ret; } else if ((t->opts->partition_offset > 0 || will_append) && sa_type == 0 && t->mbr_req_count == 0) { /* Write a simple partition table. */