Skip to content

Commit d718ff1

Browse files
committed
host/limine: Add LBA to CHS conversion code for GPT to MBR conversion
1 parent 65d43f5 commit d718ff1

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

host/limine.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,29 @@ static int gpt2mbr_type(uint64_t gpt_type1, uint64_t gpt_type2) {
185185
return -1;
186186
}
187187

188+
static void lba2chs(uint8_t *chs, uint64_t lba) {
189+
// If LBA is too big to express, use a standard value for CHS.
190+
if (lba > 63 * 255 * 1024) {
191+
goto lba_too_big;
192+
}
193+
194+
uint64_t cylinder = lba / (255 * 63);
195+
if (cylinder >= 1024) {
196+
lba_too_big:
197+
chs[0] = 0xfe;
198+
chs[1] = 0xff;
199+
chs[2] = 0xff;
200+
return;
201+
}
202+
uint64_t head = (lba / 63) % 255;
203+
uint64_t sector = (lba % 63) + 1;
204+
205+
chs[0] = head;
206+
chs[1] = (cylinder >> 2) & 0xc0; // high 2 bits
207+
chs[1] |= sector & 0x3f;
208+
chs[2] = cylinder; // low 8 bits
209+
}
210+
188211
static uint32_t crc32(void *_stream, size_t len) {
189212
uint8_t *stream = _stream;
190213
uint32_t ret = 0xffffffff;
@@ -761,6 +784,8 @@ static int bios_install(int argc, char *argv[]) {
761784
struct {
762785
uint64_t lba_start;
763786
uint64_t lba_end;
787+
uint8_t chs_start[3];
788+
uint8_t chs_end[3];
764789
uint8_t type;
765790
} part_to_conv[4];
766791
size_t part_to_conv_i = 0;
@@ -784,13 +809,16 @@ static int bios_install(int argc, char *argv[]) {
784809
goto no_mbr_conv;
785810
}
786811
part_to_conv[part_to_conv_i].lba_start = ENDSWAP(gpt_entry.starting_lba);
812+
lba2chs(part_to_conv[part_to_conv_i].chs_start, part_to_conv[part_to_conv_i].lba_start);
813+
787814
if (ENDSWAP(gpt_entry.ending_lba) > UINT32_MAX) {
788815
if (!quiet) {
789816
fprintf(stderr, "Ending LBA of partition %zu is greater than UINT32_MAX, will not convert GPT.\n", i + 1);
790817
}
791818
goto no_mbr_conv;
792819
}
793820
part_to_conv[part_to_conv_i].lba_end = ENDSWAP(gpt_entry.ending_lba);
821+
lba2chs(part_to_conv[part_to_conv_i].chs_end, part_to_conv[part_to_conv_i].lba_end);
794822

795823
int type = gpt2mbr_type(ENDSWAP(gpt_entry.partition_type_guid[0]),
796824
ENDSWAP(gpt_entry.partition_type_guid[1]));
@@ -849,6 +877,9 @@ static int bios_install(int argc, char *argv[]) {
849877
device_write(&lba_start, 0x1be + i * 16 + 0x08, 4);
850878
uint32_t sect_count = ENDSWAP((part_to_conv[i].lba_end - part_to_conv[i].lba_start) + 1);
851879
device_write(&sect_count, 0x1be + i * 16 + 0x0c, 4);
880+
881+
device_write(part_to_conv[i].chs_start, 0x1be + i * 16 + 1, 3);
882+
device_write(part_to_conv[i].chs_end, 0x1be + i * 16 + 5, 3);
852883
}
853884

854885
if (!quiet) {

0 commit comments

Comments
 (0)