Skip to content

Commit

Permalink
. 修正函数 map --unmap=
Browse files Browse the repository at this point in the history
. 增加参数 map --alloc-only,用于批处理分配自由内存。
  例如:map --alloc-only (md)0+0x1b61b0 (3) //分配0x1b61b0扇区自由扇区
        map --status=3
        set add=%?%  //返回分配的自由内存
. 加快非压缩文件(img,iso,静态vhd)加载到虚拟机内存的速度。
  • Loading branch information
yaya2007 committed Sep 1, 2024
1 parent 1cf1f8f commit 9115ba9
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 4 deletions.
8 changes: 8 additions & 0 deletions ChangeLog_UEFI.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
更新说明:
2024-09-01 (yaya)
修正函数 map --unmap=
增加参数 map --alloc-only,用于批处理分配自由内存。
例如:map --alloc-only (md)0+0x1b61b0 (3) //分配0x1b61b0扇区自由扇区
map --status=3
set add=%?% //返回分配的自由内存
加快非压缩文件(img,iso,静态vhd)加载到虚拟机内存的速度。

2024-02-26 (yaya)
改进uuid/vol函数,支持10个以上分区。

Expand Down
83 changes: 82 additions & 1 deletion stage2/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -7471,6 +7471,7 @@ map_func (char *arg, int flags) //对设备进行映射 返回: 0/1=失败/成
int prefer_top = 0;
int no_hook = 0;
int vhd_disk = 0;
int alloc_only = 0;
vhd_start_sector = 0;

//struct master_and_dos_boot_sector *BS = (struct master_and_dos_boot_sector *) RAW_ADDR (0x8000);
Expand Down Expand Up @@ -7864,6 +7865,10 @@ struct drive_map_slot
{
return 1;
}
else if (grub_memcmp (arg, "--alloc-only", 12) == 0) //仅分配内存,不用复制 2024-09-01
{
alloc_only = 1;
}
else
break;
arg = skip_to (0, arg); //跳到空格后
Expand Down Expand Up @@ -8556,11 +8561,49 @@ struct drive_map_slot
if (status != GRUB_EFI_SUCCESS) //如果失败
{
printf_errinfo ("out of map memory: %d\n",(int)status);
errnum = ERR_WONT_FIT; //2024-09-01
return 0;
}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////以上插入分配内存
/*
VHD测试
镜像:qbus_gd.vhd 716Mb(包含qbus);qbus_dt.vhd 642Mb;hdd_boot_gd.vhd(无qbus)
环境:QEMU虚拟机; VirtualBox虚拟机; 笔记本电脑。
条件1:不加载到内存/加载到内存
条件2:使用grub_read读文件簇/使用read_blocks读碎片块
条件3:U盘/SSD固态盘
--------------------------------------------------------------------------------------------------------------
环境 镜像 条件1 条件2 条件3 启动时间(秒) 说明
--------------------------------------------------------------------------------------------------------------
QEMU hdd_boot_gd.vhd map 可以正常启动
QEMU qbus_gd.vhd map 可以正常启动
QEMU qbus_gd.vhd map --mem grub_read U盘 167
QEMU qbus_gd.vhd map --mem read_blocks U盘 94
QEMU qbus_dt.vhd map 不能启动
QEMU qbus_dt.vhd map --mem grub_read U盘 93
--------------------------------------------------------------------------------------------------------------
VirtualBox hdd_boot_gd.vhd map 可以正常启动
VirtualBox qbus_gd.vhd map 不能启动(一直转圈)
VirtualBox qbus_gd.vhd map --mem grub_read U盘 503
VirtualBox qbus_gd.vhd map --mem read_blocks U盘 150
--------------------------------------------------------------------------------------------------------------
笔记本电脑 hdd_boot_gd.vhd map 可以正常启动
笔记本电脑 qbus_gd.vhd map 不能启动(转圈之后重启)
笔记本电脑 qbus_gd.vhd map --mem grub_read U盘 85
笔记本电脑 qbus_gd.vhd map --mem read_blocks U盘 82
笔记本电脑 qbus_gd.vhd map --mem grub_read SSD固态盘 2
笔记本电脑 qbus_gd.vhd map --mem read_blocks SSD固态盘 1
--------------------------------------------------------------------------------------------------------------
结论:
1. 加载速度取决于UEFI固件。实机区别不大,虚拟机有改进。
2. 静态VHD映射为硬盘,可以是内存盘,也可以不是。可以使用chainloader加载,也可以使用ntboot加载。
3. 动态/差分VHD使用chainloader加载,必须映射为内存盘。
4. 动态/差分VHD使用ntboot加载,内部必须包含BCD。
*/
mem_ok:
sector_count = bytes_needed >> 9; //扇区计数=加载到内存的扇区数,每扇区0x200字节
// sector_count = bytes_needed >> buf_geom.log2_sector_size; //扇区计数=需要扇区
Expand All @@ -8569,9 +8612,47 @@ struct drive_map_slot
if ((to == 0xffff || to == ram_drive) && !compressed_file) //如果映像在内存中,并且没有压缩,我们可以简单地移动它。
{
// if (bytes_needed != start_byte) //如果需要字节!=起始字节
if (!alloc_only) //不是仅分配 2024-09-01
{
printf ("Copying data, please wait......\n");
grub_memmove64 (alloc, start_byte, filemax);
}
}
else //如果映像不在内存中,或者被压缩
else if (!compressed_file) //如果映像不在内存,而且没有压缩(img,iso,静态vhd),使用读碎片块方法 2024-09-01 加快静态vhd的读取速度
{
//在QEMU虚拟机测试qbus_gd.vhd,716Mb,用时94秒。如果使用grub_read函数,用时167秒。94/167=56%
//在QEMU虚拟机测试qbus_dt.vhd,642Mb,用时93秒。
//在实机测试qbus_gd.vhd(ssd固态硬盘),716Mb,用时1秒。如果使用grub_read函数,用时2秒。
//在实机测试qbus_gd.vhd(2.0启动U盘),716Mb,用时82秒。如果使用grub_read函数,用时85秒。
//在Qracle VM虚拟机测试qbus_gd.vhd,716Mb,用时150秒。如果使用grub_read函数,用时503秒。150/503=30%
//静态VHD(内涵qbus)不加载到内存,QEMU虚拟机可以启动成功,Qracle VM虚拟机一直转圈,实机转圈后重启。
unsigned long long add = alloc; //内存扇区地址
filepos = skip_sectors << 9;

for (k = 0; k < blklst_num_entries; k++)
{
struct grub_disk_data *d = 0;
grub_efi_block_io_t *bio = 0;
d = get_device_by_drive (to,0);
if (!d)
return (!(errnum = ERR_NO_DISK));
bio = d->block_io; //块io
printf ("Copying data, please wait......\n");
status = efi_call_5 (bio->read_blocks, bio, bio->media->media_id, (grub_efi_uint64_t) map_start_sector[k],
(grub_efi_uintn_t) map_num_sectors[k] << 9, (char *)(grub_size_t)add); //读写(读,本身块io,media_id,扇区,字节尺寸,缓存)
if (status) //如果错误
{
grub_close (); //关闭to驱动器
errnum = ERR_READ;
return 0;
}

add += map_num_sectors[k] << 9;
filepos += map_num_sectors[k] << 9;
}
blklst_num_entries = 1; //如果文件有碎片,加载到内存后就连续了。避免后续设置碎片。
}
else //如果映像不在内存,而且被压缩,使用读文件簇方法
{
unsigned long long read_result; //读结果
unsigned long long read_size = bytes_needed; //读尺寸
Expand Down
7 changes: 4 additions & 3 deletions stage2/disk_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -2690,7 +2690,7 @@ uninstall (unsigned int drive, struct grub_disk_data *d) //释放磁盘映射

//卸载映射内存
if (d->to_drive == 0xff && d->to_log2_sector != 0xb) //内存映射
efi_call_2 (b->free_pages, d->start_sector >> 9, d->sector_count >> 3); //释放页
efi_call_2 (b->free_pages, d->start_sector << 9, d->sector_count >> 3); //释放页 2024-09-01

//卸载虚拟磁盘
if (d->vdisk) //是映射磁盘,并且挂载
Expand Down Expand Up @@ -3029,7 +3029,8 @@ grub_efidisk_readwrite (int drive, grub_disk_addr_t sector,
//动态vhd处理
if (df->vhd_disk & 1 && !vhd_read) //vhd不加载到内存,并且不是dec_vhd读磁盘
{
filepos = sector << 9;
// filepos = sector << 9;
filepos = lba_byte; //2024-09-01
dec_vhd_read ((unsigned long long)(grub_size_t)buf, (unsigned long long)size, read_write);
return 0;
}
Expand Down Expand Up @@ -4777,7 +4778,7 @@ grub_load_image (grub_efi_device_path_t *path, const char *filename, void *boot_
grub_efi_print_device_path(boot_file);
if (!boot_image)
{
//加载映像 将EFI映像加载到内存中 要读磁盘
//加载映像 将EFI映像加载到内存中 此函数要读磁盘
status = efi_call_6 (b->load_image, TRUE, //启动策略. 如果为true,则表示请求来自引导管理器,并且引导管理器正尝试将设备路径作为引导选择加载
grub_efi_image_handle, //调用方的映像句柄. 此字段用于为正在加载的映像初始化EFI加载的映像协议的父句柄字段。
boot_file, //从中加载映像的设备句柄特定文件路径
Expand Down

0 comments on commit 9115ba9

Please sign in to comment.