s2deploy: Make it big endian aware

This commit is contained in:
mintsuki 2022-03-31 07:21:52 +02:00
parent 4af966d76f
commit 2da7f5ed62

View File

@ -130,6 +130,44 @@ static uint32_t crc32(void *_stream, size_t len) {
return ret;
}
static bool bigendian = false;
static uint16_t endswap16(uint16_t value) {
uint16_t ret = 0;
ret |= (value >> 8) & 0x00ff;
ret |= (value << 8) & 0xff00;
return ret;
}
static uint32_t endswap32(uint32_t value) {
uint32_t ret = 0;
ret |= (value >> 24) & 0x000000ff;
ret |= (value >> 8) & 0x0000ff00;
ret |= (value << 8) & 0x00ff0000;
ret |= (value << 24) & 0xff000000;
return ret;
}
static uint64_t endswap64(uint64_t value) {
uint64_t ret = 0;
ret |= (value >> 56) & 0x00000000000000ff;
ret |= (value >> 40) & 0x000000000000ff00;
ret |= (value >> 24) & 0x0000000000ff0000;
ret |= (value >> 8) & 0x00000000ff000000;
ret |= (value << 8) & 0x000000ff00000000;
ret |= (value << 24) & 0x0000ff0000000000;
ret |= (value << 40) & 0x00ff000000000000;
ret |= (value << 56) & 0xff00000000000000;
return ret;
}
#define ENDSWAP(VALUE) (bigendian ? ( \
sizeof(VALUE) == 8 ? (VALUE) : \
sizeof(VALUE) == 16 ? endswap16(VALUE) : \
sizeof(VALUE) == 32 ? endswap32(VALUE) : \
sizeof(VALUE) == 64 ? endswap64(VALUE) : (abort(), 1) \
) : (VALUE))
static enum {
CACHE_CLEAN,
CACHE_DIRTY
@ -280,6 +318,10 @@ int main(int argc, char *argv[]) {
size_t bootloader_file_size = sizeof(_binary_limine_hdd_bin_data);
uint8_t orig_mbr[70], timestamp[6];
uint32_t endcheck = 0x12345678;
uint8_t endbyte = *((uint8_t *)&endcheck);
bigendian = endbyte == 0x12;
if (argc < 2) {
printf("Usage: %s <device> [GPT partition index]\n", argv[0]);
goto cleanup;
@ -324,8 +366,8 @@ int main(int argc, char *argv[]) {
struct gpt_table_header secondary_gpt_header;
if (gpt) {
fprintf(stderr, "Secondary header at LBA 0x%" PRIx64 ".\n",
gpt_header.alternate_lba);
device_read(&secondary_gpt_header, lb_size * gpt_header.alternate_lba,
ENDSWAP(gpt_header.alternate_lba));
device_read(&secondary_gpt_header, lb_size * ENDSWAP(gpt_header.alternate_lba),
sizeof(struct gpt_table_header));
if (!strncmp(secondary_gpt_header.signature, "EFI PART", 8)) {
fprintf(stderr, "Secondary header valid.\n");
@ -340,71 +382,78 @@ int main(int argc, char *argv[]) {
// Do all sanity checks on MBR
mbr = 1;
uint16_t hint = 0;
device_read(&hint, 218, sizeof(uint16_t));
if (hint != 0) {
uint8_t hint8 = 0;
uint16_t hint16 = 0;
device_read(&hint16, 218, sizeof(uint16_t));
hint16 = ENDSWAP(hint16);
if (hint16 != 0) {
if (!force_mbr) {
mbr = 0;
} else {
hint = 0;
device_write(&hint, 218, sizeof(uint16_t));
hint16 = 0;
hint16 = ENDSWAP(hint16);
device_write(&hint16, 218, sizeof(uint16_t));
}
}
device_read(&hint, 444, sizeof(uint16_t));
if (hint != 0 && hint != 0x5a5a) {
device_read(&hint16, 444, sizeof(uint16_t));
hint16 = ENDSWAP(hint16);
if (hint16 != 0 && hint16 != 0x5a5a) {
if (!force_mbr) {
mbr = 0;
} else {
hint = 0;
device_write(&hint, 444, sizeof(uint16_t));
hint16 = 0;
hint16 = ENDSWAP(hint16);
device_write(&hint16, 444, sizeof(uint16_t));
}
}
device_read(&hint, 510, sizeof(uint16_t));
if (hint != 0xaa55) {
device_read(&hint16, 510, sizeof(uint16_t));
hint16 = ENDSWAP(hint16);
if (hint16 != 0xaa55) {
if (!force_mbr) {
mbr = 0;
} else {
hint = 0xaa55;
device_write(&hint, 510, sizeof(uint16_t));
hint16 = 0xaa55;
hint16 = ENDSWAP(hint16);
device_write(&hint16, 510, sizeof(uint16_t));
}
}
device_read(&hint, 446, sizeof(uint8_t));
if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80) {
device_read(&hint8, 446, sizeof(uint8_t));
if (hint8 != 0x00 && hint8 != 0x80) {
if (!force_mbr) {
mbr = 0;
} else {
hint = (uint8_t)hint & 0x80 ? 0x80 : 0x00;
device_write(&hint, 446, sizeof(uint8_t));
hint8 = hint8 & 0x80 ? 0x80 : 0x00;
device_write(&hint8, 446, sizeof(uint8_t));
}
}
device_read(&hint, 462, sizeof(uint8_t));
if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80) {
device_read(&hint8, 462, sizeof(uint8_t));
if (hint8 != 0x00 && hint8 != 0x80) {
if (!force_mbr) {
mbr = 0;
} else {
hint = (uint8_t)hint & 0x80 ? 0x80 : 0x00;
device_write(&hint, 462, sizeof(uint8_t));
hint8 = hint8 & 0x80 ? 0x80 : 0x00;
device_write(&hint8, 462, sizeof(uint8_t));
}
}
device_read(&hint, 478, sizeof(uint8_t));
if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80) {
device_read(&hint8, 478, sizeof(uint8_t));
if (hint8 != 0x00 && hint8 != 0x80) {
if (!force_mbr) {
mbr = 0;
} else {
hint = (uint8_t)hint & 0x80 ? 0x80 : 0x00;
device_write(&hint, 478, sizeof(uint8_t));
hint8 = hint8 & 0x80 ? 0x80 : 0x00;
device_write(&hint8, 478, sizeof(uint8_t));
}
}
device_read(&hint, 494, sizeof(uint8_t));
if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80) {
device_read(&hint8, 494, sizeof(uint8_t));
if (hint8 != 0x00 && hint8 != 0x80) {
if (!force_mbr) {
mbr = 0;
} else {
hint = (uint8_t)hint & 0x80 ? 0x80 : 0x00;
device_write(&hint, 494, sizeof(uint8_t));
hint8 = hint8 & 0x80 ? 0x80 : 0x00;
device_write(&hint8, 494, sizeof(uint8_t));
}
}
@ -427,13 +476,15 @@ int main(int argc, char *argv[]) {
device_write(hintc, 54, 5);
}
}
device_read(&hint, 1080, sizeof(uint16_t));
if (hint == 0xef53) {
device_read(&hint16, 1080, sizeof(uint16_t));
hint16 = ENDSWAP(hint16);
if (hint16 == 0xef53) {
if (!force_mbr) {
mbr = 0;
} else {
hint = 0;
device_write(&hint, 1080, sizeof(uint16_t));
hint16 = 0;
hint16 = ENDSWAP(hint16);
device_write(&hint16, 1080, sizeof(uint16_t));
}
}
}
@ -463,14 +514,14 @@ int main(int argc, char *argv[]) {
uint32_t partition_num;
sscanf(argv[2], "%" SCNu32, &partition_num);
partition_num--;
if (partition_num > gpt_header.number_of_partition_entries) {
if (partition_num > ENDSWAP(gpt_header.number_of_partition_entries)) {
fprintf(stderr, "ERROR: Partition number is too large.\n");
goto cleanup;
}
struct gpt_entry gpt_entry;
device_read(&gpt_entry,
(gpt_header.partition_entry_lba * lb_size)
(ENDSWAP(gpt_header.partition_entry_lba) * lb_size)
+ (partition_num * sizeof(struct gpt_entry)),
sizeof(struct gpt_entry));
@ -482,7 +533,7 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "GPT partition specified. Installing there instead of embedding.\n");
stage2_loc_a = gpt_entry.starting_lba * lb_size;
stage2_loc_a = ENDSWAP(gpt_entry.starting_lba) * lb_size;
stage2_loc_b = stage2_loc_a + stage2_size_a;
if (stage2_loc_b & (lb_size - 1))
stage2_loc_b = (stage2_loc_b + lb_size) & ~(lb_size - 1);
@ -490,10 +541,10 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "GPT partition NOT specified. Attempting GPT embedding.\n");
int64_t max_partition_entry_used = -1;
for (int64_t i = 0; i < (int64_t)gpt_header.number_of_partition_entries; i++) {
for (int64_t i = 0; i < (int64_t)ENDSWAP(gpt_header.number_of_partition_entries); i++) {
struct gpt_entry gpt_entry;
device_read(&gpt_entry,
(gpt_header.partition_entry_lba * lb_size)
(ENDSWAP(gpt_header.partition_entry_lba) * lb_size)
+ (i * sizeof(struct gpt_entry)),
sizeof(struct gpt_entry));
@ -504,17 +555,17 @@ int main(int argc, char *argv[]) {
}
}
stage2_loc_a = (gpt_header.partition_entry_lba + 32) * lb_size;
stage2_loc_a = (ENDSWAP(gpt_header.partition_entry_lba) + 32) * lb_size;
stage2_loc_a -= stage2_size_a;
stage2_loc_a &= ~(lb_size - 1);
stage2_loc_b = (secondary_gpt_header.partition_entry_lba + 32) * lb_size;
stage2_loc_b = (ENDSWAP(secondary_gpt_header.partition_entry_lba) + 32) * lb_size;
stage2_loc_b -= stage2_size_b;
stage2_loc_b &= ~(lb_size - 1);
size_t partition_entries_per_lb =
lb_size / gpt_header.size_of_partition_entry;
lb_size / ENDSWAP(gpt_header.size_of_partition_entry);
size_t new_partition_array_lba_size =
stage2_loc_a / lb_size - gpt_header.partition_entry_lba;
stage2_loc_a / lb_size - ENDSWAP(gpt_header.partition_entry_lba);
size_t new_partition_entry_count =
new_partition_array_lba_size * partition_entries_per_lb;
@ -526,49 +577,51 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "New maximum count of partition entries: %zu.\n", new_partition_entry_count);
// Zero out unused partitions
void *empty = calloc(1, gpt_header.size_of_partition_entry);
void *empty = calloc(1, ENDSWAP(gpt_header.size_of_partition_entry));
for (size_t i = max_partition_entry_used + 1; i < new_partition_entry_count; i++) {
device_write(empty,
gpt_header.partition_entry_lba * lb_size + i * gpt_header.size_of_partition_entry,
gpt_header.size_of_partition_entry);
ENDSWAP(gpt_header.partition_entry_lba) * lb_size + i * ENDSWAP(gpt_header.size_of_partition_entry),
ENDSWAP(gpt_header.size_of_partition_entry));
}
for (size_t i = max_partition_entry_used + 1; i < new_partition_entry_count; i++) {
device_write(empty,
secondary_gpt_header.partition_entry_lba * lb_size + i * secondary_gpt_header.size_of_partition_entry,
secondary_gpt_header.size_of_partition_entry);
ENDSWAP(secondary_gpt_header.partition_entry_lba) * lb_size + i * ENDSWAP(secondary_gpt_header.size_of_partition_entry),
ENDSWAP(secondary_gpt_header.size_of_partition_entry));
}
free(empty);
uint8_t *partition_array =
malloc(new_partition_entry_count * gpt_header.size_of_partition_entry);
malloc(new_partition_entry_count * ENDSWAP(gpt_header.size_of_partition_entry));
if (partition_array == NULL) {
perror("ERROR");
goto cleanup;
}
device_read(partition_array,
gpt_header.partition_entry_lba * lb_size,
new_partition_entry_count * gpt_header.size_of_partition_entry);
ENDSWAP(gpt_header.partition_entry_lba) * lb_size,
new_partition_entry_count * ENDSWAP(gpt_header.size_of_partition_entry));
uint32_t crc32_partition_array =
crc32(partition_array,
new_partition_entry_count * gpt_header.size_of_partition_entry);
new_partition_entry_count * ENDSWAP(gpt_header.size_of_partition_entry));
free(partition_array);
gpt_header.partition_entry_array_crc32 = crc32_partition_array;
gpt_header.number_of_partition_entries = new_partition_entry_count;
gpt_header.partition_entry_array_crc32 = ENDSWAP(crc32_partition_array);
gpt_header.number_of_partition_entries = ENDSWAP(new_partition_entry_count);
gpt_header.crc32 = 0;
gpt_header.crc32 = crc32(&gpt_header, 92);
gpt_header.crc32 = ENDSWAP(gpt_header.crc32);
device_write(&gpt_header,
lb_size,
sizeof(struct gpt_table_header));
secondary_gpt_header.partition_entry_array_crc32 = crc32_partition_array;
secondary_gpt_header.partition_entry_array_crc32 = ENDSWAP(crc32_partition_array);
secondary_gpt_header.number_of_partition_entries =
new_partition_entry_count;
ENDSWAP(new_partition_entry_count);
secondary_gpt_header.crc32 = 0;
secondary_gpt_header.crc32 = crc32(&secondary_gpt_header, 92);
secondary_gpt_header.crc32 = ENDSWAP(secondary_gpt_header.crc32);
device_write(&secondary_gpt_header,
lb_size * gpt_header.alternate_lba,
sizeof(struct gpt_table_header));
@ -595,9 +648,13 @@ int main(int argc, char *argv[]) {
stage2_loc_b, stage2_size - stage2_size_a);
// Hardcode in the bootsector the location of stage 2 halves
stage2_size_a = ENDSWAP(stage2_size_a);
device_write(&stage2_size_a, 0x1a4 + 0, sizeof(uint16_t));
stage2_size_b = ENDSWAP(stage2_size_b);
device_write(&stage2_size_b, 0x1a4 + 2, sizeof(uint16_t));
stage2_loc_a = ENDSWAP(stage2_loc_a);
device_write(&stage2_loc_a, 0x1a4 + 4, sizeof(uint64_t));
stage2_loc_b = ENDSWAP(stage2_loc_b);
device_write(&stage2_loc_b, 0x1a4 + 12, sizeof(uint64_t));
// Write back timestamp