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
;
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
;
394 if (INT13_EXTENDED_READ
!= sandev
->int13_command
)
396 DBGC(sandev
, "invalid cmd %u\n", sandev
->int13_command
);
400 ix86
= (struct i386_all_regs
*)sandev
->x86_regptr
;
404 ventoy_vdisk_read_real_hdd(lba
, count
, buffer
);
405 ix86
->regs
.dl
= sandev
->drive
;
409 /* Workaround for SSTR PE loader error */
410 if (g_fixup_iso9660_secover_start
)
412 lba
= ventoy_fixup_iso9660_sector(lba
, count
);
415 readend
= (lba
+ count
) * 2048;
416 if (readend
<= g_chain
->real_img_size_in_bytes
)
418 ventoy_vdisk_read_real(lba
, count
, buffer
);
419 ix86
->regs
.dl
= sandev
->drive
;
423 if (count
> sizeof(g_sector_flag
))
425 sector_flag
= (ventoy_sector_flag
*)malloc(count
* sizeof(ventoy_sector_flag
));
428 for (curlba
= lba
, cur_flag
= sector_flag
, j
= 0; j
< count
; j
++, curlba
++, cur_flag
++)
431 for (node
= g_virt_chunk
, i
= 0; i
< g_virt_chunk_num
; i
++, node
++)
433 if (curlba
>= node
->mem_sector_start
&& curlba
< node
->mem_sector_end
)
435 memcpy((void *)(buffer
+ j
* 2048),
436 (char *)g_virt_chunk
+ node
->mem_sector_offset
+ (curlba
- node
->mem_sector_start
) * 2048,
441 else if (curlba
>= node
->remap_sector_start
&& curlba
< node
->remap_sector_end
)
443 cur_flag
->remap_lba
= node
->org_sector_start
+ curlba
- node
->remap_sector_start
;
450 for (curlba
= lba
, cur_flag
= sector_flag
, j
= 0; j
< count
; j
++, curlba
++, cur_flag
++)
452 if (cur_flag
->flag
== 2)
456 lastbuffer
= buffer
+ j
* 2048;
457 lastlba
= cur_flag
->remap_lba
;
460 else if (lastlba
+ lbacount
== cur_flag
->remap_lba
)
466 ventoy_vdisk_read_real(lastlba
, lbacount
, lastbuffer
);
467 lastbuffer
= buffer
+ j
* 2048;
468 lastlba
= cur_flag
->remap_lba
;
476 ventoy_vdisk_read_real(lastlba
, lbacount
, lastbuffer
);
479 if (sector_flag
!= g_sector_flag
)
484 ix86
->regs
.dl
= sandev
->drive
;
488 static void ventoy_dump_img_chunk(ventoy_chain_head
*chain
)
491 ventoy_img_chunk
*chunk
;
493 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
495 printf("##################### ventoy_dump_img_chunk #######################\n");
497 for (i
= 0; i
< chain
->img_chunk_num
; i
++)
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
);
504 ventoy_debug_pause();
507 static void ventoy_dump_override_chunk(ventoy_chain_head
*chain
)
510 ventoy_override_chunk
*chunk
;
512 chunk
= (ventoy_override_chunk
*)((char *)chain
+ chain
->override_chunk_offset
);
514 printf("##################### ventoy_dump_override_chunk #######################\n");
516 for (i
= 0; i
< g_override_chunk_num
; i
++)
518 printf("%2u: [ %llu, %u ]\n", i
, chunk
[i
].img_offset
, chunk
[i
].override_size
);
521 ventoy_debug_pause();
524 static void ventoy_dump_virt_chunk(ventoy_chain_head
*chain
)
527 ventoy_virt_chunk
*node
;
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
);
533 node
= (ventoy_virt_chunk
*)((char *)chain
+ chain
->virt_chunk_offset
);
534 for (i
= 0; i
< chain
->virt_chunk_num
; i
++, node
++)
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
);
545 ventoy_debug_pause();
548 static void ventoy_dump_chain(ventoy_chain_head
*chain
)
554 uint8_t *vtoy_reserve
;
556 guid
= chain
->os_param
.vtoy_disk_guid
;
557 sig
= chain
->os_param
.vtoy_disk_signature
;
559 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
561 chksum
+= *((uint8_t *)(&(chain
->os_param
)) + i
);
564 vtoy_reserve
= (uint8_t *)(chain
->os_param
.vtoy_reserved
);
566 printf("##################### ventoy_dump_chain #######################\n");
568 printf("os_param will be save at %p\n", ventoy_get_runtime_addr());
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();
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();
600 ventoy_dump_img_chunk(chain
);
601 ventoy_dump_override_chunk(chain
);
602 ventoy_dump_virt_chunk(chain
);
605 static int ventoy_update_image_location(ventoy_os_param
*param
)
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
;
615 length
= sizeof(ventoy_image_location
) + (g_img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
617 address
= umalloc(length
+ 4096 * 2);
625 address
+= 4096 - (address
% 4096);
629 param
->vtoy_img_location_addr
= user_to_phys(address
, 0);
630 param
->vtoy_img_location_len
= length
;
632 /* update check sum */
633 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
635 chksum
+= *((uint8_t *)param
+ i
);
637 param
->chksum
= (chksum
== 0) ? 0 : (uint8_t)(0x100 - chksum
);
639 location
= (ventoy_image_location
*)(unsigned long)(address
);
640 if (NULL
== location
)
645 memcpy(&location
->guid
, ¶m
->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
;
650 region
= location
->regions
;
654 for (i
= 0; i
< g_img_chunk_num
; i
++)
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
;
665 for (i
= 0; i
< g_img_chunk_num
; i
++)
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
;
678 int ventoy_boot_vdisk(void *data
)
683 ventoy_img_chunk
*cur
;
687 ventoy_address
.bufsize
= offsetof ( typeof ( ventoy_address
), buffer_phys
);
689 if (strstr(g_cmdline_copy
, "debug"))
692 printf("### ventoy chain boot begin... ###\n");
693 printf("cmdline: <%s>\n", g_cmdline_copy
);
694 ventoy_debug_pause();
697 if (strstr(g_cmdline_copy
, "sector512"))
702 if (strstr(g_cmdline_copy
, "bios80"))
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
;
713 g_os_param_reserved
= (uint8_t *)(g_chain
->os_param
.vtoy_reserved
);
715 /* Workaround for Windows & ISO9660 */
716 if (g_os_param_reserved
[2] == ventoy_chain_windows
&& g_os_param_reserved
[3] == 0)
718 g_fixup_iso9660_secover_enable
= 1;
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
;
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
;
729 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
731 chksum
+= *((uint8_t *)(&(g_chain
->os_param
)) + i
);
733 printf("os param checksum: 0x%x %s\n", g_chain
->os_param
.chksum
, chksum
? "FAILED" : "SUCCESS");
736 ventoy_update_image_location(&(g_chain
->os_param
));
740 ventoy_dump_chain(g_chain
);
745 for (i
= 0; i
< g_img_chunk_num
; i
++)
748 cur
->img_start_sector
*= 4;
749 cur
->img_end_sector
= cur
->img_end_sector
* 4 + 3;
753 drive
= ventoy_int13_hook(g_chain
);
757 printf("### ventoy chain boot before boot image ... ###\n");
758 ventoy_debug_pause();
761 ventoy_int13_boot(drive
, &(g_chain
->os_param
), g_cmdline_copy
);
765 printf("!!!!!!!!!! ventoy boot failed !!!!!!!!!!\n");
766 ventoy_debug_pause();