]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - IPXE/ipxe_mod_code/ipxe-3fe683e/src/arch/x86/core/ventoy_vdisk.c
0224b8aba0ddf785d25f6c8ecca71a12512e40e2
[Ventoy.git] / IPXE / ipxe_mod_code / ipxe-3fe683e / src / arch / x86 / core / ventoy_vdisk.c
1
2 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
3
4 #include <stdint.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <limits.h>
8 #include <byteswap.h>
9 #include <errno.h>
10 #include <assert.h>
11 #include <ipxe/blockdev.h>
12 #include <ipxe/io.h>
13 #include <ipxe/acpi.h>
14 #include <ipxe/sanboot.h>
15 #include <ipxe/device.h>
16 #include <ipxe/pci.h>
17 #include <ipxe/eltorito.h>
18 #include <ipxe/timer.h>
19 #include <ipxe/umalloc.h>
20 #include <realmode.h>
21 #include <bios.h>
22 #include <biosint.h>
23 #include <bootsector.h>
24 #include <int13.h>
25 #include <ventoy.h>
26
27 int g_debug = 0;
28 int g_hddmode = 0;
29 int g_bios_disk80 = 0;
30 char *g_cmdline_copy;
31 void *g_initrd_addr;
32 size_t g_initrd_len;
33 ventoy_chain_head *g_chain;
34 ventoy_img_chunk *g_chunk;
35 uint32_t g_img_chunk_num;
36 ventoy_img_chunk *g_cur_chunk;
37 uint32_t g_disk_sector_size;
38 uint8_t *g_os_param_reserved;
39
40
41 ventoy_override_chunk *g_override_chunk;
42 uint32_t g_override_chunk_num;
43
44 ventoy_virt_chunk *g_virt_chunk;
45 uint32_t g_virt_chunk_num;
46
47 ventoy_sector_flag g_sector_flag[128];
48
49 #define VENTOY_ISO9660_SECTOR_OVERFLOW 2097152
50
51 int g_fixup_iso9660_secover_enable = 0;
52 int g_fixup_iso9660_secover_start = 0;
53 uint64 g_fixup_iso9660_secover_1st_secs = 0;
54 uint64 g_fixup_iso9660_secover_cur_secs = 0;
55 uint64 g_fixup_iso9660_secover_tot_secs = 0;
56
57 static struct int13_disk_address __bss16 ( ventoy_address );
58 #define ventoy_address __use_data16 ( ventoy_address )
59
60 static uint64_t ventoy_remap_lba_hdd(uint64_t lba, uint32_t *count)
61 {
62 uint32_t i;
63 uint32_t max_sectors;
64 ventoy_img_chunk *cur;
65
66 if ((NULL == g_cur_chunk) || (lba < g_cur_chunk->img_start_sector) ||
67 (lba > g_cur_chunk->img_end_sector))
68 {
69 g_cur_chunk = NULL;
70 for (i = 0; i < g_img_chunk_num; i++)
71 {
72 cur = g_chunk + i;
73 if (lba >= cur->img_start_sector && lba <= cur->img_end_sector)
74 {
75 g_cur_chunk = cur;
76 break;
77 }
78 }
79 }
80
81 if (g_cur_chunk)
82 {
83 max_sectors = g_cur_chunk->img_end_sector - lba + 1;
84 if (*count > max_sectors)
85 {
86 *count = max_sectors;
87 }
88
89 return g_cur_chunk->disk_start_sector + (lba - g_cur_chunk->img_start_sector);
90 }
91 return lba;
92 }
93
94 static uint64_t ventoy_remap_lba(uint64_t lba, uint32_t *count)
95 {
96 uint32_t i;
97 uint32_t max_sectors;
98 ventoy_img_chunk *cur;
99
100 if ((NULL == g_cur_chunk) || ((lba) < g_cur_chunk->img_start_sector) || ((lba) > g_cur_chunk->img_end_sector))
101 {
102 g_cur_chunk = NULL;
103 for (i = 0; i < g_img_chunk_num; i++)
104 {
105 cur = g_chunk + i;
106 if (lba >= cur->img_start_sector && lba <= cur->img_end_sector)
107 {
108 g_cur_chunk = cur;
109 break;
110 }
111 }
112 }
113
114 if (g_cur_chunk)
115 {
116 max_sectors = g_cur_chunk->img_end_sector - lba + 1;
117 if (*count > max_sectors)
118 {
119 *count = max_sectors;
120 }
121
122 if (512 == g_disk_sector_size)
123 {
124 return g_cur_chunk->disk_start_sector + ((lba - g_cur_chunk->img_start_sector) << 2);
125 }
126 return g_cur_chunk->disk_start_sector + (lba - g_cur_chunk->img_start_sector) * 2048 / g_disk_sector_size;
127 }
128 return lba;
129 }
130
131 static int ventoy_vdisk_read_real_hdd(uint64_t lba, unsigned int count, unsigned long buffer)
132 {
133 uint32_t left = 0;
134 uint32_t readcount = 0;
135 uint32_t tmpcount = 0;
136 uint16_t status = 0;
137 uint64_t curlba = 0;
138 uint64_t maplba = 0;
139 unsigned long phyaddr;
140
141 curlba = lba;
142 left = count;
143
144 #if VTOY_DEBUG
145 printf("ventoy_vdisk_read_real_hdd: %llu %u\n", lba, count);
146 #endif
147
148 while (left > 0)
149 {
150 readcount = left;
151 maplba = ventoy_remap_lba_hdd(curlba, &readcount);
152
153 tmpcount = readcount;
154
155 phyaddr = user_to_phys(buffer, 0);
156
157 while (tmpcount > 0)
158 {
159 /* Use INT 13, 42 to read the data from real disk */
160 ventoy_address.lba = maplba;
161 ventoy_address.buffer.segment = (uint16_t)(phyaddr >> 4);
162 ventoy_address.buffer.offset = (uint16_t)(phyaddr & 0x0F);
163
164 if (tmpcount >= 64) /* max sectors per transmit */
165 {
166 ventoy_address.count = 64;
167 tmpcount -= 64;
168 maplba += 64;
169 phyaddr += 32768;
170 }
171 else
172 {
173 ventoy_address.count = tmpcount;
174 tmpcount = 0;
175 }
176
177 __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
178 "sti\n\t"
179 "int $0x13\n\t"
180 "sti\n\t" /* BIOS bugs */
181 "jc 1f\n\t"
182 "xorw %%ax, %%ax\n\t"
183 "\n1:\n\t" )
184 : "=a" ( status )
185 : "a" ( 0x4200 ), "d" ( VENTOY_BIOS_FAKE_DRIVE ),
186 "S" ( __from_data16 ( &ventoy_address ) ) );
187 }
188
189 curlba += readcount;
190 left -= readcount;
191 buffer += (readcount * 512);
192 }
193
194 return 0;
195 }
196
197 static int ventoy_vdisk_read_real(uint64_t lba, unsigned int count, unsigned long buffer)
198 {
199 uint32_t i = 0;
200 uint32_t left = 0;
201 uint32_t readcount = 0;
202 uint32_t tmpcount = 0;
203 uint16_t status = 0;
204 uint64_t curlba = 0;
205 uint64_t maplba = 0;
206 uint64_t start = 0;
207 uint64_t end = 0;
208 uint64_t override_start = 0;
209 uint64_t override_end = 0;
210 unsigned long phyaddr;
211 unsigned long databuffer = buffer;
212 uint8_t *override_data;
213
214 curlba = lba;
215 left = count;
216
217 while (left > 0)
218 {
219 readcount = left;
220 maplba = ventoy_remap_lba(curlba, &readcount);
221
222 if (g_disk_sector_size == 512)
223 {
224 tmpcount = (readcount << 2);
225 }
226 else
227 {
228 tmpcount = (readcount * 2048) / g_disk_sector_size;
229 }
230
231 phyaddr = user_to_phys(buffer, 0);
232
233 while (tmpcount > 0)
234 {
235 /* Use INT 13, 42 to read the data from real disk */
236 ventoy_address.lba = maplba;
237 ventoy_address.buffer.segment = (uint16_t)(phyaddr >> 4);
238 ventoy_address.buffer.offset = (uint16_t)(phyaddr & 0x0F);
239
240 if (tmpcount >= 64) /* max sectors per transmit */
241 {
242 ventoy_address.count = 64;
243 tmpcount -= 64;
244 maplba += 64;
245 phyaddr += 32768;
246 }
247 else
248 {
249 ventoy_address.count = tmpcount;
250 tmpcount = 0;
251 }
252
253 __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
254 "sti\n\t"
255 "int $0x13\n\t"
256 "sti\n\t" /* BIOS bugs */
257 "jc 1f\n\t"
258 "xorw %%ax, %%ax\n\t"
259 "\n1:\n\t" )
260 : "=a" ( status )
261 : "a" ( 0x4200 ), "d" ( VENTOY_BIOS_FAKE_DRIVE ),
262 "S" ( __from_data16 ( &ventoy_address ) ) );
263 }
264
265 curlba += readcount;
266 left -= readcount;
267 buffer += (readcount * 2048);
268 }
269
270 start = lba * 2048;
271 if (start > g_chain->real_img_size_in_bytes)
272 {
273 goto end;
274 }
275
276 end = start + count * 2048;
277 for (i = 0; i < g_override_chunk_num; i++)
278 {
279 override_data = g_override_chunk[i].override_data;
280 override_start = g_override_chunk[i].img_offset;
281 override_end = override_start + g_override_chunk[i].override_size;
282
283 if (end <= override_start || start >= override_end)
284 {
285 continue;
286 }
287
288 if (start <= override_start)
289 {
290 if (end <= override_end)
291 {
292 memcpy((char *)databuffer + override_start - start, override_data, end - override_start);
293 }
294 else
295 {
296 memcpy((char *)databuffer + override_start - start, override_data, override_end - override_start);
297 }
298 }
299 else
300 {
301 if (end <= override_end)
302 {
303 memcpy((char *)databuffer, override_data + start - override_start, end - start);
304 }
305 else
306 {
307 memcpy((char *)databuffer, override_data + start - override_start, override_end - start);
308 }
309 }
310
311 if (g_fixup_iso9660_secover_enable && (!g_fixup_iso9660_secover_start) &&
312 g_override_chunk[i].override_size == sizeof(ventoy_iso9660_override))
313 {
314 ventoy_iso9660_override *dirent = (ventoy_iso9660_override *)override_data;
315 if (dirent->first_sector >= VENTOY_ISO9660_SECTOR_OVERFLOW)
316 {
317 g_fixup_iso9660_secover_start = 1;
318 g_fixup_iso9660_secover_cur_secs = 0;
319 }
320 }
321 }
322
323 end:
324
325 return 0;
326 }
327
328 uint64_t ventoy_fixup_iso9660_sector(uint64_t Lba, uint32_t secNum)
329 {
330 uint32_t i = 0;
331
332 if (g_fixup_iso9660_secover_cur_secs > 0)
333 {
334 Lba += VENTOY_ISO9660_SECTOR_OVERFLOW;
335 g_fixup_iso9660_secover_cur_secs += secNum;
336 if (g_fixup_iso9660_secover_cur_secs >= g_fixup_iso9660_secover_tot_secs)
337 {
338 g_fixup_iso9660_secover_start = 0;
339 goto end;
340 }
341 }
342 else
343 {
344 ventoy_iso9660_override *dirent;
345 ventoy_override_chunk *pOverride;
346
347 for (i = 0, pOverride = g_override_chunk; i < g_override_chunk_num; i++, pOverride++)
348 {
349 dirent = (ventoy_iso9660_override *)pOverride->override_data;
350 if (Lba == dirent->first_sector)
351 {
352 g_fixup_iso9660_secover_start = 0;
353 goto end;
354 }
355 }
356
357 if (g_fixup_iso9660_secover_start)
358 {
359 for (i = 0, pOverride = g_override_chunk; i < g_override_chunk_num; i++, pOverride++)
360 {
361 dirent = (ventoy_iso9660_override *)pOverride->override_data;
362 if (Lba + VENTOY_ISO9660_SECTOR_OVERFLOW == dirent->first_sector)
363 {
364 g_fixup_iso9660_secover_tot_secs = (dirent->size + 2047) / 2048;
365 g_fixup_iso9660_secover_cur_secs = secNum;
366 if (g_fixup_iso9660_secover_cur_secs >= g_fixup_iso9660_secover_tot_secs)
367 {
368 g_fixup_iso9660_secover_start = 0;
369 }
370 Lba += VENTOY_ISO9660_SECTOR_OVERFLOW;
371 goto end;
372 }
373 }
374 }
375 }
376
377 end:
378 return Lba;
379 }
380
381 int ventoy_vdisk_read(struct san_device *sandev, uint64_t lba, unsigned int count, unsigned long buffer)
382 {
383 uint32_t i, j;
384 uint64_t curlba;
385 uint64_t lastlba = 0;
386 uint32_t lbacount = 0;
387 unsigned long lastbuffer;
388 uint64_t readend;
389 ventoy_virt_chunk *node;
390 ventoy_sector_flag *cur_flag;
391 ventoy_sector_flag *sector_flag = g_sector_flag;
392 struct i386_all_regs *ix86;
393
394 if (INT13_EXTENDED_READ != sandev->int13_command)
395 {
396 DBGC(sandev, "invalid cmd %u\n", sandev->int13_command);
397 return 0;
398 }
399
400 ix86 = (struct i386_all_regs *)sandev->x86_regptr;
401
402 if (g_hddmode)
403 {
404 ventoy_vdisk_read_real_hdd(lba, count, buffer);
405 ix86->regs.dl = sandev->drive;
406 return 0;
407 }
408
409 /* Workaround for SSTR PE loader error */
410 if (g_fixup_iso9660_secover_start)
411 {
412 lba = ventoy_fixup_iso9660_sector(lba, count);
413 }
414
415 readend = (lba + count) * 2048;
416 if (readend <= g_chain->real_img_size_in_bytes)
417 {
418 ventoy_vdisk_read_real(lba, count, buffer);
419 ix86->regs.dl = sandev->drive;
420 return 0;
421 }
422
423 if (count > sizeof(g_sector_flag))
424 {
425 sector_flag = (ventoy_sector_flag *)malloc(count * sizeof(ventoy_sector_flag));
426 }
427
428 for (curlba = lba, cur_flag = sector_flag, j = 0; j < count; j++, curlba++, cur_flag++)
429 {
430 cur_flag->flag = 0;
431 for (node = g_virt_chunk, i = 0; i < g_virt_chunk_num; i++, node++)
432 {
433 if (curlba >= node->mem_sector_start && curlba < node->mem_sector_end)
434 {
435 memcpy((void *)(buffer + j * 2048),
436 (char *)g_virt_chunk + node->mem_sector_offset + (curlba - node->mem_sector_start) * 2048,
437 2048);
438 cur_flag->flag = 1;
439 break;
440 }
441 else if (curlba >= node->remap_sector_start && curlba < node->remap_sector_end)
442 {
443 cur_flag->remap_lba = node->org_sector_start + curlba - node->remap_sector_start;
444 cur_flag->flag = 2;
445 break;
446 }
447 }
448 }
449
450 for (curlba = lba, cur_flag = sector_flag, j = 0; j < count; j++, curlba++, cur_flag++)
451 {
452 if (cur_flag->flag == 2)
453 {
454 if (lastlba == 0)
455 {
456 lastbuffer = buffer + j * 2048;
457 lastlba = cur_flag->remap_lba;
458 lbacount = 1;
459 }
460 else if (lastlba + lbacount == cur_flag->remap_lba)
461 {
462 lbacount++;
463 }
464 else
465 {
466 ventoy_vdisk_read_real(lastlba, lbacount, lastbuffer);
467 lastbuffer = buffer + j * 2048;
468 lastlba = cur_flag->remap_lba;
469 lbacount = 1;
470 }
471 }
472 }
473
474 if (lbacount > 0)
475 {
476 ventoy_vdisk_read_real(lastlba, lbacount, lastbuffer);
477 }
478
479 if (sector_flag != g_sector_flag)
480 {
481 free(sector_flag);
482 }
483
484 ix86->regs.dl = sandev->drive;
485 return 0;
486 }
487
488 static void ventoy_dump_img_chunk(ventoy_chain_head *chain)
489 {
490 uint32_t i;
491 ventoy_img_chunk *chunk;
492
493 chunk = (ventoy_img_chunk *)((char *)chain + chain->img_chunk_offset);
494
495 printf("##################### ventoy_dump_img_chunk #######################\n");
496
497 for (i = 0; i < chain->img_chunk_num; i++)
498 {
499 printf("%2u: [ %u - %u ] <==> [ %llu - %llu ]\n",
500 i, chunk[i].img_start_sector, chunk[i].img_end_sector,
501 chunk[i].disk_start_sector, chunk[i].disk_end_sector);
502 }
503
504 ventoy_debug_pause();
505 }
506
507 static void ventoy_dump_override_chunk(ventoy_chain_head *chain)
508 {
509 uint32_t i;
510 ventoy_override_chunk *chunk;
511
512 chunk = (ventoy_override_chunk *)((char *)chain + chain->override_chunk_offset);
513
514 printf("##################### ventoy_dump_override_chunk #######################\n");
515
516 for (i = 0; i < g_override_chunk_num; i++)
517 {
518 printf("%2u: [ %llu, %u ]\n", i, chunk[i].img_offset, chunk[i].override_size);
519 }
520
521 ventoy_debug_pause();
522 }
523
524 static void ventoy_dump_virt_chunk(ventoy_chain_head *chain)
525 {
526 uint32_t i;
527 ventoy_virt_chunk *node;
528
529 printf("##################### ventoy_dump_virt_chunk #######################\n");
530 printf("virt_chunk_offset=%u\n", chain->virt_chunk_offset);
531 printf("virt_chunk_num=%u\n", chain->virt_chunk_num);
532
533 node = (ventoy_virt_chunk *)((char *)chain + chain->virt_chunk_offset);
534 for (i = 0; i < chain->virt_chunk_num; i++, node++)
535 {
536 printf("%2u: mem:[ %u, %u, %u ] remap:[ %u, %u, %u ]\n", i,
537 node->mem_sector_start,
538 node->mem_sector_end,
539 node->mem_sector_offset,
540 node->remap_sector_start,
541 node->remap_sector_end,
542 node->org_sector_start);
543 }
544
545 ventoy_debug_pause();
546 }
547
548 static void ventoy_dump_chain(ventoy_chain_head *chain)
549 {
550 uint32_t i = 0;
551 uint8_t chksum = 0;
552 uint8_t *guid;
553 uint8_t *sig;
554 uint8_t *vtoy_reserve;
555
556 guid = chain->os_param.vtoy_disk_guid;
557 sig = chain->os_param.vtoy_disk_signature;
558
559 for (i = 0; i < sizeof(ventoy_os_param); i++)
560 {
561 chksum += *((uint8_t *)(&(chain->os_param)) + i);
562 }
563
564 vtoy_reserve = (uint8_t *)(chain->os_param.vtoy_reserved);
565
566 printf("##################### ventoy_dump_chain #######################\n");
567
568 printf("os_param will be save at %p\n", ventoy_get_runtime_addr());
569
570 printf("os_param->chksum=0x%x (%s)\n", chain->os_param.chksum, chksum ? "FAILED" : "SUCCESS");
571 printf("os_param->vtoy_disk_guid=%02x%02x%02x%02x\n", guid[0], guid[1], guid[2], guid[3]);
572 printf("os_param->vtoy_disk_signature=%02x%02x%02x%02x\n", sig[0], sig[1], sig[2], sig[3]);
573 printf("os_param->vtoy_disk_size=%llu\n", chain->os_param.vtoy_disk_size);
574 printf("os_param->vtoy_disk_part_id=%u\n", chain->os_param.vtoy_disk_part_id);
575 printf("os_param->vtoy_disk_part_type=%u\n", chain->os_param.vtoy_disk_part_type);
576 printf("os_param->vtoy_img_path=<%s>\n", chain->os_param.vtoy_img_path);
577 printf("os_param->vtoy_img_size=<%llu>\n", chain->os_param.vtoy_img_size);
578 printf("os_param->vtoy_reserve[0]=<%u>\n", vtoy_reserve[0]);
579 printf("os_param->vtoy_reserve[1]=<%u>\n", vtoy_reserve[1]);
580 printf("os_param->vtoy_reserve[2]=<%u>\n", vtoy_reserve[2]);
581 printf("os_param->vtoy_reserve[3]=<%u>\n", vtoy_reserve[3]);
582 printf("os_param->vtoy_img_location_addr=<0x%llx>\n", chain->os_param.vtoy_img_location_addr);
583 printf("os_param->vtoy_img_location_len=<%u>\n", chain->os_param.vtoy_img_location_len);
584 ventoy_debug_pause();
585
586 printf("chain->disk_drive=0x%x\n", chain->disk_drive);
587 printf("chain->drive_map=0x%x\n", chain->drive_map);
588 printf("chain->disk_sector_size=%u\n", chain->disk_sector_size);
589 printf("chain->real_img_size_in_bytes=%llu\n", chain->real_img_size_in_bytes);
590 printf("chain->virt_img_size_in_bytes=%llu\n", chain->virt_img_size_in_bytes);
591 printf("chain->boot_catalog=%u\n", chain->boot_catalog);
592 printf("chain->img_chunk_offset=%u\n", chain->img_chunk_offset);
593 printf("chain->img_chunk_num=%u\n", chain->img_chunk_num);
594 printf("chain->override_chunk_offset=%u\n", chain->override_chunk_offset);
595 printf("chain->override_chunk_num=%u\n", chain->override_chunk_num);
596 printf("chain->virt_chunk_offset=%u\n", chain->virt_chunk_offset);
597 printf("chain->virt_chunk_num=%u\n", chain->virt_chunk_num);
598 ventoy_debug_pause();
599
600 ventoy_dump_img_chunk(chain);
601 ventoy_dump_override_chunk(chain);
602 ventoy_dump_virt_chunk(chain);
603 }
604
605 static int ventoy_update_image_location(ventoy_os_param *param)
606 {
607 uint8_t chksum = 0;
608 unsigned int i;
609 unsigned int length;
610 userptr_t address = 0;
611 ventoy_image_location *location = NULL;
612 ventoy_image_disk_region *region = NULL;
613 ventoy_img_chunk *chunk = g_chunk;
614
615 length = sizeof(ventoy_image_location) + (g_img_chunk_num - 1) * sizeof(ventoy_image_disk_region);
616
617 address = umalloc(length + 4096 * 2);
618 if (!address)
619 {
620 return 0;
621 }
622
623 if (address % 4096)
624 {
625 address += 4096 - (address % 4096);
626 }
627
628 param->chksum = 0;
629 param->vtoy_img_location_addr = user_to_phys(address, 0);
630 param->vtoy_img_location_len = length;
631
632 /* update check sum */
633 for (i = 0; i < sizeof(ventoy_os_param); i++)
634 {
635 chksum += *((uint8_t *)param + i);
636 }
637 param->chksum = (chksum == 0) ? 0 : (uint8_t)(0x100 - chksum);
638
639 location = (ventoy_image_location *)(unsigned long)(address);
640 if (NULL == location)
641 {
642 return 0;
643 }
644
645 memcpy(&location->guid, &param->guid, sizeof(ventoy_guid));
646 location->image_sector_size = g_hddmode ? 512 : 2048;
647 location->disk_sector_size = g_chain->disk_sector_size;
648 location->region_count = g_img_chunk_num;
649
650 region = location->regions;
651
652 if (g_hddmode)
653 {
654 for (i = 0; i < g_img_chunk_num; i++)
655 {
656 region->image_sector_count = chunk->disk_end_sector - chunk->disk_start_sector + 1;
657 region->image_start_sector = chunk->img_start_sector * 4;
658 region->disk_start_sector = chunk->disk_start_sector;
659 region++;
660 chunk++;
661 }
662 }
663 else
664 {
665 for (i = 0; i < g_img_chunk_num; i++)
666 {
667 region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
668 region->image_start_sector = chunk->img_start_sector;
669 region->disk_start_sector = chunk->disk_start_sector;
670 region++;
671 chunk++;
672 }
673 }
674
675 return 0;
676 }
677
678 int ventoy_boot_vdisk(void *data)
679 {
680 uint8_t chksum = 0;
681 unsigned int i;
682 unsigned int drive;
683 ventoy_img_chunk *cur;
684
685 (void)data;
686
687 ventoy_address.bufsize = offsetof ( typeof ( ventoy_address ), buffer_phys );
688
689 if (strstr(g_cmdline_copy, "debug"))
690 {
691 g_debug = 1;
692 printf("### ventoy chain boot begin... ###\n");
693 printf("cmdline: <%s>\n", g_cmdline_copy);
694 ventoy_debug_pause();
695 }
696
697 if (strstr(g_cmdline_copy, "sector512"))
698 {
699 g_hddmode = 1;
700 }
701
702 if (strstr(g_cmdline_copy, "bios80"))
703 {
704 g_bios_disk80 = 1;
705 }
706
707 g_chain = (ventoy_chain_head *)g_initrd_addr;
708 g_chunk = (ventoy_img_chunk *)((char *)g_chain + g_chain->img_chunk_offset);
709 g_img_chunk_num = g_chain->img_chunk_num;
710 g_disk_sector_size = g_chain->disk_sector_size;
711 g_cur_chunk = g_chunk;
712
713 g_os_param_reserved = (uint8_t *)(g_chain->os_param.vtoy_reserved);
714
715 /* Workaround for Windows & ISO9660 */
716 if (g_os_param_reserved[2] == ventoy_chain_windows && g_os_param_reserved[3] == 0)
717 {
718 g_fixup_iso9660_secover_enable = 1;
719 }
720
721 g_override_chunk = (ventoy_override_chunk *)((char *)g_chain + g_chain->override_chunk_offset);
722 g_override_chunk_num = g_chain->override_chunk_num;
723
724 g_virt_chunk = (ventoy_virt_chunk *)((char *)g_chain + g_chain->virt_chunk_offset);
725 g_virt_chunk_num = g_chain->virt_chunk_num;
726
727 if (g_debug)
728 {
729 for (i = 0; i < sizeof(ventoy_os_param); i++)
730 {
731 chksum += *((uint8_t *)(&(g_chain->os_param)) + i);
732 }
733 printf("os param checksum: 0x%x %s\n", g_chain->os_param.chksum, chksum ? "FAILED" : "SUCCESS");
734 }
735
736 ventoy_update_image_location(&(g_chain->os_param));
737
738 if (g_debug)
739 {
740 ventoy_dump_chain(g_chain);
741 }
742
743 if (g_hddmode)
744 {
745 for (i = 0; i < g_img_chunk_num; i++)
746 {
747 cur = g_chunk + i;
748 cur->img_start_sector *= 4;
749 cur->img_end_sector = cur->img_end_sector * 4 + 3;
750 }
751 }
752
753 drive = ventoy_int13_hook(g_chain);
754
755 if (g_debug)
756 {
757 printf("### ventoy chain boot before boot image ... ###\n");
758 ventoy_debug_pause();
759 }
760
761 ventoy_int13_boot(drive, &(g_chain->os_param), g_cmdline_copy);
762
763 if (g_debug)
764 {
765 printf("!!!!!!!!!! ventoy boot failed !!!!!!!!!!\n");
766 ventoy_debug_pause();
767 }
768
769 return 0;
770 }
771