2 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL
);
11 #include <ipxe/blockdev.h>
13 #include <ipxe/acpi.h>
14 #include <ipxe/sanboot.h>
15 #include <ipxe/device.h>
17 #include <ipxe/eltorito.h>
18 #include <ipxe/timer.h>
19 #include <ipxe/umalloc.h>
23 #include <bootsector.h>
29 int g_bios_disk80
= 0;
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
;
41 ventoy_override_chunk
*g_override_chunk
;
42 uint32_t g_override_chunk_num
;
44 ventoy_virt_chunk
*g_virt_chunk
;
45 uint32_t g_virt_chunk_num
;
47 ventoy_sector_flag g_sector_flag
[128];
49 #define VENTOY_ISO9660_SECTOR_OVERFLOW 2097152
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;
57 static struct int13_disk_address
__bss16 ( ventoy_address
);
58 #define ventoy_address __use_data16 ( ventoy_address )
60 static uint64_t ventoy_remap_lba_hdd(uint64_t lba
, uint32_t *count
)
64 ventoy_img_chunk
*cur
;
66 if ((NULL
== g_cur_chunk
) || (lba
< g_cur_chunk
->img_start_sector
) ||
67 (lba
> g_cur_chunk
->img_end_sector
))
70 for (i
= 0; i
< g_img_chunk_num
; i
++)
73 if (lba
>= cur
->img_start_sector
&& lba
<= cur
->img_end_sector
)
83 max_sectors
= g_cur_chunk
->img_end_sector
- lba
+ 1;
84 if (*count
> max_sectors
)
89 return g_cur_chunk
->disk_start_sector
+ (lba
- g_cur_chunk
->img_start_sector
);
94 static uint64_t ventoy_remap_lba(uint64_t lba
, uint32_t *count
)
98 ventoy_img_chunk
*cur
;
100 if ((NULL
== g_cur_chunk
) || ((lba
) < g_cur_chunk
->img_start_sector
) || ((lba
) > g_cur_chunk
->img_end_sector
))
103 for (i
= 0; i
< g_img_chunk_num
; i
++)
106 if (lba
>= cur
->img_start_sector
&& lba
<= cur
->img_end_sector
)
116 max_sectors
= g_cur_chunk
->img_end_sector
- lba
+ 1;
117 if (*count
> max_sectors
)
119 *count
= max_sectors
;
122 if (512 == g_disk_sector_size
)
124 return g_cur_chunk
->disk_start_sector
+ ((lba
- g_cur_chunk
->img_start_sector
) << 2);
126 return g_cur_chunk
->disk_start_sector
+ (lba
- g_cur_chunk
->img_start_sector
) * 2048 / g_disk_sector_size
;
131 static int ventoy_vdisk_read_real_hdd(uint64_t lba
, unsigned int count
, unsigned long buffer
)
134 uint32_t readcount
= 0;
135 uint32_t tmpcount
= 0;
139 unsigned long phyaddr
;
145 printf("ventoy_vdisk_read_real_hdd: %llu %u\n", lba
, count
);
151 maplba
= ventoy_remap_lba_hdd(curlba
, &readcount
);
153 tmpcount
= readcount
;
155 phyaddr
= user_to_phys(buffer
, 0);
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);
164 if (tmpcount
>= 64) /* max sectors per transmit */
166 ventoy_address
.count
= 64;
173 ventoy_address
.count
= tmpcount
;
177 __asm__
__volatile__ ( REAL_CODE ( "stc\n\t"
180 "sti\n\t" /* BIOS bugs */
182 "xorw %%ax, %%ax\n\t"
185 : "a" ( 0x4200 ), "d" ( VENTOY_BIOS_FAKE_DRIVE
),
186 "S" ( __from_data16 ( &ventoy_address
) ) );
191 buffer
+= (readcount
* 512);
197 static int ventoy_vdisk_read_real(uint64_t lba
, unsigned int count
, unsigned long buffer
)
201 uint32_t readcount
= 0;
202 uint32_t tmpcount
= 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
;
220 maplba
= ventoy_remap_lba(curlba
, &readcount
);
222 if (g_disk_sector_size
== 512)
224 tmpcount
= (readcount
<< 2);
228 tmpcount
= (readcount
* 2048) / g_disk_sector_size
;
231 phyaddr
= user_to_phys(buffer
, 0);
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);
240 if (tmpcount
>= 64) /* max sectors per transmit */
242 ventoy_address
.count
= 64;
249 ventoy_address
.count
= tmpcount
;
253 __asm__
__volatile__ ( REAL_CODE ( "stc\n\t"
256 "sti\n\t" /* BIOS bugs */
258 "xorw %%ax, %%ax\n\t"
261 : "a" ( 0x4200 ), "d" ( VENTOY_BIOS_FAKE_DRIVE
),
262 "S" ( __from_data16 ( &ventoy_address
) ) );
267 buffer
+= (readcount
* 2048);
271 if (start
> g_chain
->real_img_size_in_bytes
)
276 end
= start
+ count
* 2048;
277 for (i
= 0; i
< g_override_chunk_num
; i
++)
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
;
283 if (end
<= override_start
|| start
>= override_end
)
288 if (start
<= override_start
)
290 if (end
<= override_end
)
292 memcpy((char *)databuffer
+ override_start
- start
, override_data
, end
- override_start
);
296 memcpy((char *)databuffer
+ override_start
- start
, override_data
, override_end
- override_start
);
301 if (end
<= override_end
)
303 memcpy((char *)databuffer
, override_data
+ start
- override_start
, end
- start
);
307 memcpy((char *)databuffer
, override_data
+ start
- override_start
, override_end
- start
);
311 if (g_fixup_iso9660_secover_enable
&& (!g_fixup_iso9660_secover_start
) &&
312 g_override_chunk
[i
].override_size
== sizeof(ventoy_iso9660_override
))
314 ventoy_iso9660_override
*dirent
= (ventoy_iso9660_override
*)override_data
;
315 if (dirent
->first_sector
>= VENTOY_ISO9660_SECTOR_OVERFLOW
)
317 g_fixup_iso9660_secover_start
= 1;
318 g_fixup_iso9660_secover_cur_secs
= 0;
328 uint64_t ventoy_fixup_iso9660_sector(uint64_t Lba
, uint32_t secNum
)
332 if (g_fixup_iso9660_secover_cur_secs
> 0)
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
)
338 g_fixup_iso9660_secover_start
= 0;
344 ventoy_iso9660_override
*dirent
;
345 ventoy_override_chunk
*pOverride
;
347 for (i
= 0, pOverride
= g_override_chunk
; i
< g_override_chunk_num
; i
++, pOverride
++)
349 dirent
= (ventoy_iso9660_override
*)pOverride
->override_data
;
350 if (Lba
== dirent
->first_sector
)
352 g_fixup_iso9660_secover_start
= 0;
357 if (g_fixup_iso9660_secover_start
)
359 for (i
= 0, pOverride
= g_override_chunk
; i
< g_override_chunk_num
; i
++, pOverride
++)
361 dirent
= (ventoy_iso9660_override
*)pOverride
->override_data
;
362 if (Lba
+ VENTOY_ISO9660_SECTOR_OVERFLOW
== dirent
->first_sector
)
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
)
368 g_fixup_iso9660_secover_start
= 0;
370 Lba
+= VENTOY_ISO9660_SECTOR_OVERFLOW
;
381 int ventoy_vdisk_read(struct san_device
*sandev
, uint64_t lba
, unsigned int count
, unsigned long buffer
)
385 uint64_t lastlba
= 0;
386 uint32_t lbacount
= 0;
387 unsigned long lastbuffer
;
390 ventoy_virt_chunk
*node
;
391 ventoy_sector_flag
*cur_flag
;
392 ventoy_sector_flag
*sector_flag
= g_sector_flag
;
393 struct i386_all_regs
*ix86
;
395 if (INT13_EXTENDED_READ
!= sandev
->int13_command
)
397 DBGC(sandev
, "invalid cmd %u\n", sandev
->int13_command
);
401 ix86
= (struct i386_all_regs
*)sandev
->x86_regptr
;
406 /* need to check ?? */
407 lastlba
= g_chain
->virt_img_size_in_bytes
/ 512;
410 if (lba
+ count
> lastlba
)
412 count
= lastlba
- lba
;
414 ventoy_vdisk_read_real_hdd(lba
, count
, buffer
);
418 ventoy_vdisk_read_real_hdd(lba
, count
, buffer
);
419 ix86
->regs
.dl
= sandev
->drive
;
423 /* Workaround for SSTR PE loader error */
424 if (g_fixup_iso9660_secover_start
)
426 lba
= ventoy_fixup_iso9660_sector(lba
, count
);
429 readend
= (lba
+ count
) * 2048;
430 if (readend
<= g_chain
->real_img_size_in_bytes
)
432 ventoy_vdisk_read_real(lba
, count
, buffer
);
433 ix86
->regs
.dl
= sandev
->drive
;
436 else if ((lba
* 2048) < g_chain
->real_img_size_in_bytes
)
438 /* fix for grub4dos Inconsistent data read from error */
439 memset((void *)(buffer
+ (count
- 1) * 2048), 0, 2048);
441 count
= (g_chain
->real_img_size_in_bytes
/ 2048) - lba
;
442 ventoy_vdisk_read_real(lba
, count
, buffer
);
443 ix86
->regs
.dl
= sandev
->drive
;
446 buffer
+= count
* 2048;
447 count
= (readend
- g_chain
->real_img_size_in_bytes
) / 2048;
450 VirtSec
= g_chain
->virt_img_size_in_bytes
/ 2048;
453 /* fix for grub4dos Inconsistent data read from error */
454 memset((void *)(buffer
+ (count
- 1) * 2048), 0, 2048);
456 ix86
->regs
.dl
= sandev
->drive
;
459 else if (lba
+ count
> VirtSec
)
461 count
= VirtSec
- lba
;
464 if (count
> sizeof(g_sector_flag
))
466 sector_flag
= (ventoy_sector_flag
*)malloc(count
* sizeof(ventoy_sector_flag
));
469 for (curlba
= lba
, cur_flag
= sector_flag
, j
= 0; j
< count
; j
++, curlba
++, cur_flag
++)
472 for (node
= g_virt_chunk
, i
= 0; i
< g_virt_chunk_num
; i
++, node
++)
474 if (curlba
>= node
->mem_sector_start
&& curlba
< node
->mem_sector_end
)
476 memcpy((void *)(buffer
+ j
* 2048),
477 (char *)g_virt_chunk
+ node
->mem_sector_offset
+ (curlba
- node
->mem_sector_start
) * 2048,
482 else if (curlba
>= node
->remap_sector_start
&& curlba
< node
->remap_sector_end
)
484 cur_flag
->remap_lba
= node
->org_sector_start
+ curlba
- node
->remap_sector_start
;
491 for (curlba
= lba
, cur_flag
= sector_flag
, j
= 0; j
< count
; j
++, curlba
++, cur_flag
++)
493 if (cur_flag
->flag
== 2)
497 lastbuffer
= buffer
+ j
* 2048;
498 lastlba
= cur_flag
->remap_lba
;
501 else if (lastlba
+ lbacount
== cur_flag
->remap_lba
)
507 ventoy_vdisk_read_real(lastlba
, lbacount
, lastbuffer
);
508 lastbuffer
= buffer
+ j
* 2048;
509 lastlba
= cur_flag
->remap_lba
;
517 ventoy_vdisk_read_real(lastlba
, lbacount
, lastbuffer
);
520 if (sector_flag
!= g_sector_flag
)
525 ix86
->regs
.dl
= sandev
->drive
;
529 static void ventoy_dump_img_chunk(ventoy_chain_head
*chain
)
532 ventoy_img_chunk
*chunk
;
534 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
536 printf("##################### ventoy_dump_img_chunk #######################\n");
538 for (i
= 0; i
< chain
->img_chunk_num
; i
++)
540 printf("%2u: [ %u - %u ] <==> [ %llu - %llu ]\n",
541 i
, chunk
[i
].img_start_sector
, chunk
[i
].img_end_sector
,
542 chunk
[i
].disk_start_sector
, chunk
[i
].disk_end_sector
);
545 ventoy_debug_pause();
548 static void ventoy_dump_override_chunk(ventoy_chain_head
*chain
)
551 ventoy_override_chunk
*chunk
;
553 chunk
= (ventoy_override_chunk
*)((char *)chain
+ chain
->override_chunk_offset
);
555 printf("##################### ventoy_dump_override_chunk #######################\n");
557 for (i
= 0; i
< g_override_chunk_num
; i
++)
559 printf("%2u: [ %llu, %u ]\n", i
, chunk
[i
].img_offset
, chunk
[i
].override_size
);
562 ventoy_debug_pause();
565 static void ventoy_dump_virt_chunk(ventoy_chain_head
*chain
)
568 ventoy_virt_chunk
*node
;
570 printf("##################### ventoy_dump_virt_chunk #######################\n");
571 printf("virt_chunk_offset=%u\n", chain
->virt_chunk_offset
);
572 printf("virt_chunk_num=%u\n", chain
->virt_chunk_num
);
574 node
= (ventoy_virt_chunk
*)((char *)chain
+ chain
->virt_chunk_offset
);
575 for (i
= 0; i
< chain
->virt_chunk_num
; i
++, node
++)
577 printf("%2u: mem:[ %u, %u, %u ] remap:[ %u, %u, %u ]\n", i
,
578 node
->mem_sector_start
,
579 node
->mem_sector_end
,
580 node
->mem_sector_offset
,
581 node
->remap_sector_start
,
582 node
->remap_sector_end
,
583 node
->org_sector_start
);
586 ventoy_debug_pause();
589 static void ventoy_dump_chain(ventoy_chain_head
*chain
)
595 uint8_t *vtoy_reserve
;
597 guid
= chain
->os_param
.vtoy_disk_guid
;
598 sig
= chain
->os_param
.vtoy_disk_signature
;
600 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
602 chksum
+= *((uint8_t *)(&(chain
->os_param
)) + i
);
605 vtoy_reserve
= (uint8_t *)(chain
->os_param
.vtoy_reserved
);
607 printf("##################### ventoy_dump_chain #######################\n");
609 printf("os_param will be save at %p\n", ventoy_get_runtime_addr());
611 printf("os_param->chksum=0x%x (%s)\n", chain
->os_param
.chksum
, chksum
? "FAILED" : "SUCCESS");
612 printf("os_param->vtoy_disk_guid=%02x%02x%02x%02x\n", guid
[0], guid
[1], guid
[2], guid
[3]);
613 printf("os_param->vtoy_disk_signature=%02x%02x%02x%02x\n", sig
[0], sig
[1], sig
[2], sig
[3]);
614 printf("os_param->vtoy_disk_size=%llu\n", chain
->os_param
.vtoy_disk_size
);
615 printf("os_param->vtoy_disk_part_id=%u\n", chain
->os_param
.vtoy_disk_part_id
);
616 printf("os_param->vtoy_disk_part_type=%u\n", chain
->os_param
.vtoy_disk_part_type
);
617 printf("os_param->vtoy_img_path=<%s>\n", chain
->os_param
.vtoy_img_path
);
618 printf("os_param->vtoy_img_size=<%llu>\n", chain
->os_param
.vtoy_img_size
);
619 printf("os_param->vtoy_reserve[0]=<%u>\n", vtoy_reserve
[0]);
620 printf("os_param->vtoy_reserve[1]=<%u>\n", vtoy_reserve
[1]);
621 printf("os_param->vtoy_reserve[2]=<%u>\n", vtoy_reserve
[2]);
622 printf("os_param->vtoy_reserve[3]=<%u>\n", vtoy_reserve
[3]);
623 printf("os_param->vtoy_img_location_addr=<0x%llx>\n", chain
->os_param
.vtoy_img_location_addr
);
624 printf("os_param->vtoy_img_location_len=<%u>\n", chain
->os_param
.vtoy_img_location_len
);
625 ventoy_debug_pause();
627 printf("chain->disk_drive=0x%x\n", chain
->disk_drive
);
628 printf("chain->drive_map=0x%x\n", chain
->drive_map
);
629 printf("chain->disk_sector_size=%u\n", chain
->disk_sector_size
);
630 printf("chain->real_img_size_in_bytes=%llu\n", chain
->real_img_size_in_bytes
);
631 printf("chain->virt_img_size_in_bytes=%llu\n", chain
->virt_img_size_in_bytes
);
632 printf("chain->boot_catalog=%u\n", chain
->boot_catalog
);
633 printf("chain->img_chunk_offset=%u\n", chain
->img_chunk_offset
);
634 printf("chain->img_chunk_num=%u\n", chain
->img_chunk_num
);
635 printf("chain->override_chunk_offset=%u\n", chain
->override_chunk_offset
);
636 printf("chain->override_chunk_num=%u\n", chain
->override_chunk_num
);
637 printf("chain->virt_chunk_offset=%u\n", chain
->virt_chunk_offset
);
638 printf("chain->virt_chunk_num=%u\n", chain
->virt_chunk_num
);
639 ventoy_debug_pause();
641 ventoy_dump_img_chunk(chain
);
642 ventoy_dump_override_chunk(chain
);
643 ventoy_dump_virt_chunk(chain
);
646 static int ventoy_update_image_location(ventoy_os_param
*param
)
651 userptr_t address
= 0;
652 ventoy_image_location
*location
= NULL
;
653 ventoy_image_disk_region
*region
= NULL
;
654 ventoy_img_chunk
*chunk
= g_chunk
;
656 length
= sizeof(ventoy_image_location
) + (g_img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
658 address
= umalloc(length
+ 4096 * 2);
666 address
+= 4096 - (address
% 4096);
670 param
->vtoy_img_location_addr
= user_to_phys(address
, 0);
671 param
->vtoy_img_location_len
= length
;
673 /* update check sum */
674 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
676 chksum
+= *((uint8_t *)param
+ i
);
678 param
->chksum
= (chksum
== 0) ? 0 : (uint8_t)(0x100 - chksum
);
680 location
= (ventoy_image_location
*)(unsigned long)(address
);
681 if (NULL
== location
)
686 memcpy(&location
->guid
, ¶m
->guid
, sizeof(ventoy_guid
));
687 location
->image_sector_size
= g_hddmode
? 512 : 2048;
688 location
->disk_sector_size
= g_chain
->disk_sector_size
;
689 location
->region_count
= g_img_chunk_num
;
691 region
= location
->regions
;
695 for (i
= 0; i
< g_img_chunk_num
; i
++)
697 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
698 region
->image_start_sector
= chunk
->img_start_sector
* 4;
699 region
->disk_start_sector
= chunk
->disk_start_sector
;
706 for (i
= 0; i
< g_img_chunk_num
; i
++)
708 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
709 region
->image_start_sector
= chunk
->img_start_sector
;
710 region
->disk_start_sector
= chunk
->disk_start_sector
;
719 int ventoy_boot_vdisk(void *data
)
724 ventoy_img_chunk
*cur
;
728 ventoy_address
.bufsize
= offsetof ( typeof ( ventoy_address
), buffer_phys
);
730 if (strstr(g_cmdline_copy
, "debug"))
733 printf("### ventoy chain boot begin... ###\n");
734 printf("cmdline: <%s>\n", g_cmdline_copy
);
735 ventoy_debug_pause();
738 if (strstr(g_cmdline_copy
, "sector512"))
743 if (strstr(g_cmdline_copy
, "bios80"))
748 g_chain
= (ventoy_chain_head
*)g_initrd_addr
;
749 g_chunk
= (ventoy_img_chunk
*)((char *)g_chain
+ g_chain
->img_chunk_offset
);
750 g_img_chunk_num
= g_chain
->img_chunk_num
;
751 g_disk_sector_size
= g_chain
->disk_sector_size
;
752 g_cur_chunk
= g_chunk
;
754 g_os_param_reserved
= (uint8_t *)(g_chain
->os_param
.vtoy_reserved
);
756 /* Workaround for Windows & ISO9660 */
757 if (g_os_param_reserved
[2] == ventoy_chain_windows
&& g_os_param_reserved
[3] == 0)
759 g_fixup_iso9660_secover_enable
= 1;
762 g_override_chunk
= (ventoy_override_chunk
*)((char *)g_chain
+ g_chain
->override_chunk_offset
);
763 g_override_chunk_num
= g_chain
->override_chunk_num
;
765 g_virt_chunk
= (ventoy_virt_chunk
*)((char *)g_chain
+ g_chain
->virt_chunk_offset
);
766 g_virt_chunk_num
= g_chain
->virt_chunk_num
;
770 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
772 chksum
+= *((uint8_t *)(&(g_chain
->os_param
)) + i
);
774 printf("os param checksum: 0x%x %s\n", g_chain
->os_param
.chksum
, chksum
? "FAILED" : "SUCCESS");
777 ventoy_update_image_location(&(g_chain
->os_param
));
781 ventoy_dump_chain(g_chain
);
786 for (i
= 0; i
< g_img_chunk_num
; i
++)
789 cur
->img_start_sector
*= 4;
790 cur
->img_end_sector
= cur
->img_end_sector
* 4 + 3;
794 drive
= ventoy_int13_hook(g_chain
);
798 printf("### ventoy chain boot before boot image ... ###\n");
799 ventoy_debug_pause();
802 ventoy_int13_boot(drive
, &(g_chain
->os_param
), g_cmdline_copy
);
806 printf("!!!!!!!!!! ventoy boot failed !!!!!!!!!!\n");
807 ventoy_debug_pause();