New system area type 2 for Little Endian MIPS DEC boot block.

This commit is contained in:
Thomas Schmitt 2010-10-14 22:34:32 +02:00
parent a0ba4b976c
commit a75fb9a894
4 changed files with 215 additions and 19 deletions

View File

@ -16,13 +16,17 @@ specifications, some is just rumor which happens to work (maybe not even that).
EL Torito CD booting, for PC-BIOS x86, PowerPC, (old) Mac, EFI. EL Torito CD booting, for PC-BIOS x86, PowerPC, (old) Mac, EFI.
MBR, for PC-BIOS x86 from (pseudo-) hard disk MBR, for PC-BIOS x86 from (pseudo-) hard disk
- SYSLINUX Isohybrid MBR - SYSLINUX isohybrid MBR
- GRUB2 grub-mkrescue MBR. - GRUB2 grub-mkrescue MBR.
MIPS Volume Header, for MIPS Big Endian, e.g. SGI Indigo2. MIPS Volume Header, for MIPS Big Endian, e.g. SGI Indigo2.
DEC Boot Block, for MIPS Little Endian , e.g. DECstation.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
EL Torito CD booting EL Torito CD booting
for PC-BIOS x86, PowerPC, (old) Mac, EFI for PC-BIOS x86, PowerPC, (old) Mac, EFI
@ -239,9 +243,9 @@ Byte Range | Value | Meaning
24 - 63 | 0 | Reserved 24 - 63 | 0 | Reserved
---------- | ---------- | ---------------------------------------------------- ---------- | ---------- | ----------------------------------------------------
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
MBR MBR
for PC-BIOS x86 from (pseudo-) hard disk for PC-BIOS x86 from (pseudo-) hard disk
@ -480,7 +484,9 @@ Cleartext part:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
MIPSEL Little Endian MIPS , e.g. DECstation
DEC Boot Block
for MIPS Little Endian , e.g. DECstation
Sources: Sources:
cdrkit-1.1.10/genisoimage/boot-mipsel.c cdrkit-1.1.10/genisoimage/boot-mipsel.c
@ -495,6 +501,7 @@ Sources:
There seems to be only one boot file possible. There seems to be only one boot file possible.
Some information needs to be read out of the ELF headers of this boot file.
Byte Range | Value | Meaning Byte Range | Value | Meaning
---------- | ---------- | ---------------------------------------------------- ---------- | ---------- | ----------------------------------------------------
@ -514,12 +521,13 @@ Byte Range | Value | Meaning
| | | |
24 - 31 | ========== | Boot Map Entry 1 24 - 31 | ========== | Boot Map Entry 1
| | | |
24 - 27 | count | Segment size in file. 24 - 27 | seg_size | Segment size in file. Blocks of 512 bytes.
| | Stems from ELF header of boot file. | | Stems from ELF header of boot file.
| | (Elf32_Phdr field p_filesz + 511) / 512; | | (Elf32_Phdr field p_filesz + 511) / 512;
| | | |
28 - 31 | start | Segment file offset 28 - 31 | seg_start | Segment file offset. Blocks 512 bytes.
| | Stems from ELF header of boot file. | | ISO 9660 LBA of boot file * 4 plus offset
| | + offset which stems from ELF header of boot file:
| | (Elf32_Phdr field p_offset + 511) / 512; | | (Elf32_Phdr field p_offset + 511) / 512;
| | | |
32 - 431 | ========== | Boot Map Entries 2 to 51 32 - 431 | ========== | Boot Map Entries 2 to 51
@ -547,15 +555,15 @@ Byte Range | Value | Meaning
0 - 3 | | ( Segment type ) 0 - 3 | | ( Segment type )
| | | |
4 - 7 | p_offset | /* Segment file offset */ 4 - 7 | p_offset | /* Segment file offset */
| -> start | Needed for start |-> seg_start| Needed for seg_start
| | | |
8 - 11 | p_vaddr | /* Segment virtual address */ 8 - 11 | p_vaddr | /* Segment virtual address */
=load_address| Needed for load_address | =load_adr | Needed for load_adr
| | | |
12 - 15 | | (Segment physical address) 12 - 15 | | (Segment physical address)
| | | |
16 - 19 | p_filesz | /* Segment size in file */ 16 - 19 | p_filesz | /* Segment size in file */
| -> count | Needed for count |-> seg_size | Needed for seg_size
| | | |

View File

@ -1775,6 +1775,11 @@ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size);
* iso_image_add_mips_boot_file(). * iso_image_add_mips_boot_file().
* This will overwrite the first 512 bytes of the submitted * This will overwrite the first 512 bytes of the submitted
* data. * data.
* 2= DEC Boot Block for MIPS Little Endian
* The first boot file submitted by
* iso_image_add_mips_boot_file() will be activated.
* This will overwrite the first 512 bytes of the submitted
* data.
* @param flag * @param flag
* bit0 = invalidate any attached system area data. Same as data == NULL * bit0 = invalidate any attached system area data. Same as data == NULL
* (This re-activates eventually loaded image System Area data. * (This re-activates eventually loaded image System Area data.
@ -2970,9 +2975,13 @@ int iso_image_get_system_area(IsoImage *img, char data[32768],
int *options, int flag); int *options, int flag);
/** /**
* Add a MIPS Big Endian boot file path to the image. Up to 15 such files can * Add a MIPS boot file path to the image.
* be written into a MIPS Big Endian Volume Header if this is enabled by * Up to 15 such files can be written into a MIPS Big Endian Volume Header
* value 1 in iso_write_opts_set_system_area() option bits 2 to 7. * if this is enabled by value 1 in iso_write_opts_set_system_area() option
* bits 2 to 7.
* A single file can be written into a DEC Boot Block if this is enabled by
* value 2 in iso_write_opts_set_system_area() option bits 2 to 7. So only
* the first added file gets into effect with this system area type.
* The data files which shall serve as MIPS boot files have to be brought into * The data files which shall serve as MIPS boot files have to be brought into
* the image by the normal means. * the image by the normal means.
* @param img * @param img
@ -6315,8 +6324,8 @@ int iso_md5_match(char first_md5[16], char second_md5[16]);
/** Too many MIPS Big Endian boot files given (max. 15) (FAILURE, HIGH, -365)*/ /** Too many MIPS Big Endian boot files given (max. 15) (FAILURE, HIGH, -365)*/
#define ISO_BOOT_TOO_MANY_MIPS 0xE830FE91 #define ISO_BOOT_TOO_MANY_MIPS 0xE830FE91
/** MIPS Big Endian boot file missing in image (MISHAP, HIGH, -364) */ /** Boot file missing in image (MISHAP, HIGH, -364) */
#define ISO_BOOT_MIPS_MISSING 0xE430FE90 #define ISO_BOOT_FILE_MISSING 0xE430FE90

View File

@ -352,8 +352,8 @@ const char *iso_error_to_msg(int errcode)
return "Failed to process file for Jigdo Template Extraction"; return "Failed to process file for Jigdo Template Extraction";
case ISO_BOOT_TOO_MANY_MIPS: case ISO_BOOT_TOO_MANY_MIPS:
return "Too many MIPS Big Endian boot files given (max. 15)"; return "Too many MIPS Big Endian boot files given (max. 15)";
case ISO_BOOT_MIPS_MISSING: case ISO_BOOT_FILE_MISSING:
return "MIPS Big Endian boot file missing in image"; return "Boot file missing in image";
default: default:
return "Unknown error"; return "Unknown error";
} }

View File

@ -212,6 +212,41 @@ int iso_offset_partition_start(uint32_t img_blocks, uint32_t partition_offset,
} }
static int boot_nodes_from_iso_path(Ecma119Image *t, char *path,
IsoNode **iso_node, Ecma119Node **ecma_node,
char *purpose, int flag)
{
int ret;
ret = iso_tree_path_to_node(t->image, path, iso_node);
if (ret < 0) {
iso_msg_submit(t->image->id, ISO_BOOT_FILE_MISSING, 0,
"Cannot find %s '%s'", purpose, path);
return ISO_BOOT_FILE_MISSING;
}
if ((*iso_node)->type != LIBISO_FILE) {
iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
"Designated boot file is not a data file: '%s'", path);
return ISO_BOOT_IMAGE_NOT_VALID;
}
*ecma_node= ecma119_search_iso_node(t, *iso_node);
if (*ecma_node == NULL) {
iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
"Program error: IsoFile has no Ecma119Node: '%s'", path);
return ISO_ASSERT_FAILURE;
} else {
if ((*ecma_node)->type != ECMA119_FILE) {
iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
"Program error: Ecma119Node of IsoFile is no ECMA119_FILE: '%s'",
path);
return ISO_ASSERT_FAILURE;
}
}
return ISO_SUCCESS;
}
/* This function was implemented according to doc/boot_sectors.txt section /* This function was implemented according to doc/boot_sectors.txt section
"MIPS Volume Header" which was derived by Thomas Schmitt from "MIPS Volume Header" which was derived by Thomas Schmitt from
cdrkit-1.1.10/genisoimage/boot-mips.c by Steve McIntyre which is based cdrkit-1.1.10/genisoimage/boot-mips.c by Steve McIntyre which is based
@ -273,13 +308,27 @@ static int make_mips_volume_header(Ecma119Image *t, uint8_t *buf, int flag)
#ifdef Libisofs_mips_boot_file_pathS #ifdef Libisofs_mips_boot_file_pathS
for (idx = 0; idx < t->image->num_mips_boot_files; idx++) { for (idx = 0; idx < t->image->num_mips_boot_files; idx++) {
#ifndef NIX
ret = boot_nodes_from_iso_path(t, t->image->mips_boot_file_paths[idx],
&node, &ecma_node, "MIPS boot file", 0);
if (ret < 0)
return ret;
namept = (char *) iso_node_get_name(node);
name_field = (char *) (buf + (72 + 16 * idx));
strncpy(name_field, namept, 8);
#else /* ! NIX */
ret = iso_tree_path_to_node(t->image, ret = iso_tree_path_to_node(t->image,
t->image->mips_boot_file_paths[idx], &node); t->image->mips_boot_file_paths[idx], &node);
if (ret < 0) { if (ret < 0) {
iso_msg_submit(t->image->id, ISO_BOOT_MIPS_MISSING, 0, iso_msg_submit(t->image->id, ISO_BOOT_FILE_MISSING, 0,
"Cannot find MIPS boot file '%s'", "Cannot find MIPS boot file '%s'",
t->image->mips_boot_file_paths[idx]); t->image->mips_boot_file_paths[idx]);
return ISO_BOOT_MIPS_MISSING; return ISO_BOOT_FILE_MISSING;
} }
if (node->type != LIBISO_FILE) { if (node->type != LIBISO_FILE) {
iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
@ -306,6 +355,10 @@ static int make_mips_volume_header(Ecma119Image *t, uint8_t *buf, int flag)
t->image->mips_boot_file_paths[idx]); t->image->mips_boot_file_paths[idx]);
return ISO_ASSERT_FAILURE; return ISO_ASSERT_FAILURE;
} }
#endif /* NIX */
file_lba = ecma_node->info.file->sections[0].block; file_lba = ecma_node->info.file->sections[0].block;
iso_msb(buf + (72 + 16 * idx) + 8, file_lba * 4, 4); iso_msb(buf + (72 + 16 * idx) + 8, file_lba * 4, 4);
@ -365,7 +418,129 @@ static int make_mips_volume_header(Ecma119Image *t, uint8_t *buf, int flag)
} }
iso_msb(buf + 504, checksum, 4); iso_msb(buf + 504, checksum, 4);
return 1; return ISO_SUCCESS;
}
/* This function was implemented according to doc/boot_sectors.txt section
"MIPS Little Endian" which was derived by Thomas Schmitt from
cdrkit-1.1.10/genisoimage/boot-mipsel.c by Steve McIntyre which is based
on work of Florian Lohoff and Thiemo Seufer, and from <elf.h> by Free
Software Foundation, Inc.
This function itself is entirely under copyright (C) 2010 Thomas Schmitt.
*/
static int make_mipsel_volume_header(Ecma119Image *t, uint8_t *buf, int flag)
{
uint32_t load_adr, exec_adr, seg_size, seg_start, p_offset, p_filesz;
uint32_t phdr_adr;
off_t image_size;
int ret;
uint8_t elf_buf[32];
char *path = NULL;
IsoNode *iso_node;
Ecma119Node *ecma_node;
IsoStream *stream;
FILE *fp = NULL;
/* Bytes 512 to 32767 may come from image or external file */
memset(buf, 0, 512);
/* <<< Unused. No partition table or such ? */
image_size = t->curblock * 2048;
if (t->image->num_mips_boot_files <= 0)
return ISO_SUCCESS; /* There seems to be no partition table */
ret = boot_nodes_from_iso_path(t, t->image->mips_boot_file_paths[0],
&iso_node, &ecma_node, "MIPS boot file", 0);
if (ret < 0)
return ret;
stream = iso_file_get_stream((IsoFile *) iso_node);
/* <<< This does not work for boot file in old session */
/* >>> Replace by iso_stream_open(), iso_stream_read() which has to be
done earlier, or system area production must happen before
iso_image_create_burn_source() ends.
*/
path= iso_stream_get_source_path(stream, 0);
if (path == NULL) {
iso_msg_submit(t->image->id, ISO_ASSERT_FAILURE, 0,
"Cannot determine disk path of designated MIPS boot file: '%s'",
t->image->mips_boot_file_paths[0]);
return ISO_ASSERT_FAILURE;
}
fp = fopen(path, "r");
if (fp == NULL) {
cannot_read:;
iso_msg_submit(t->image->id, ISO_FILE_ERROR, 0,
"Cannot open designated MIPS boot file: '%s'",
path[0]);
if (fp != NULL)
fclose(fp);
free(path);
return ISO_FILE_ERROR;
}
free(path);
path = NULL;
/* Read necessary ELF info */
ret = fread(elf_buf, 32, 1, fp);
if (ret != 1)
goto cannot_read;
/* 24 - 27 | e_entry | Entry point virtual address */
exec_adr = iso_read_lsb(elf_buf + 24, 4);
/* 28 - 31 | e_phoff | Program header table file offset */
phdr_adr = iso_read_lsb(elf_buf + 28, 4);
/* <<< This does not work for boot file in old session */
/* >>> replace by skip-reading of stream data */
ret = fseek(fp, (long) phdr_adr, SEEK_SET);
if (ret != 1)
goto cannot_read;
ret = fread(elf_buf, 20, 1, fp);
if (ret != 1)
goto cannot_read;
/* 4 - 7 | p_offset | Segment file offset */
p_offset = iso_read_lsb(elf_buf + 4, 4);
/* 8 - 11 | p_vaddr | Segment virtual address */
load_adr = iso_read_lsb(elf_buf + 8, 4);
/* 16 - 19 | p_filesz | Segment size in file */
p_filesz = iso_read_lsb(elf_buf + 16, 4);
fclose(fp);
fp = NULL;
/* Write DEC Bootblock */
/* 8 - 11 | 0x0002757a | Magic number */
iso_lsb(buf + 8, 0x0002757a, 4);
/* 12 - 15 | 1 | Mode 1: Multi extent boot */
iso_lsb(buf + 12, 1, 4);
/* 16 - 19 | load_adr | Load address */
iso_lsb(buf + 16, load_adr, 4);
/* 20 - 23 | exec_adr | Execution address */
iso_lsb(buf + 20, exec_adr, 4);
/* 24 - 27 | seg_size | Segment size in file. */
seg_size = (p_filesz + 511) / 512;
iso_lsb(buf + 24, seg_size, 4);
/* 28 - 31 | seg_start | Segment file offset */
seg_start = ecma_node->info.file->sections[0].block * 4
+ (p_offset + 511) / 512;
iso_lsb(buf + 28, seg_start, 4);
return ISO_SUCCESS;
} }
@ -426,6 +601,10 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
ret = make_mips_volume_header(t, buf, 0); ret = make_mips_volume_header(t, buf, 0);
if (ret != ISO_SUCCESS) if (ret != ISO_SUCCESS)
return ret; return ret;
} else if(sa_type == 2) {
ret = make_mipsel_volume_header(t, buf, 0);
if (ret != ISO_SUCCESS)
return ret;
} else if(t->partition_offset > 0 && sa_type == 0) { } else if(t->partition_offset > 0 && sa_type == 0) {
/* Write a simple partition table. */ /* Write a simple partition table. */
ret = make_grub_msdos_label(img_blocks, buf, 2); ret = make_grub_msdos_label(img_blocks, buf, 2);