From b685a8c9bed3bf71f7faa23603b24d1ed185ae9a Mon Sep 17 00:00:00 2001 From: yaya Date: Sat, 9 Jan 2021 21:33:39 +0800 Subject: [PATCH] =?UTF-8?q?=EF=BB=BF.=20=E5=90=AF=E5=8A=A8=20bootmgfw.efi?= =?UTF-8?q?=20=E3=80=82=20.=20=E4=BF=AE=E6=AD=A3=20graphicsmode=EF=BC=8Cdi?= =?UTF-8?q?splaymem=20=E5=87=BD=E6=95=B0=E3=80=82=20.=20=E6=96=B0=E8=AE=BE?= =?UTF-8?q?=E5=86=85=E9=83=A8=E5=8F=98=E9=87=8F=EF=BC=9A=200x8272(1?= =?UTF-8?q?=E5=AD=97=E8=8A=82)=20UEFI=20=E5=90=AF=E5=8A=A8=E7=8E=AF?= =?UTF-8?q?=E5=A2=83(32/64=E4=BD=8D)=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChangeLog_UEFI.txt | 6 + menu.lst | 3 + stage2/asm.S | 22 ++- stage2/builtins.c | 451 ++++++++++++++++++++++++++++----------------- stage2/common.c | 22 ++- stage2/dec_vhd.c | 85 +++++---- stage2/disk_io.c | 243 +++++++++++++++++------- stage2/gunzip.c | 1 + stage2/pc_slice.h | 5 + stage2/shared.h | 71 ++++--- stage2/stage2.c | 3 +- 11 files changed, 585 insertions(+), 327 deletions(-) diff --git a/ChangeLog_UEFI.txt b/ChangeLog_UEFI.txt index 7469731e..61e3fd1c 100644 --- a/ChangeLog_UEFI.txt +++ b/ChangeLog_UEFI.txt @@ -1,6 +1,12 @@ 更新说明: +2021-01-09 (yaya) + 启动 bootmgfw.efi 。 + 修正 graphicsmode,displaymem 函数。 + 新设内部变量: 0x8272(1字节) UEFI 启动环境(32/64位)。 + 2020-12-15 (a1ive) 添加 load 命令以加载 EFI 驱动。 + 2020-12-14 (yaya) 一次编译完成32位、64位版本。 diff --git a/menu.lst b/menu.lst index d5f80067..ac7c2359 100644 --- a/menu.lst +++ b/menu.lst @@ -37,6 +37,9 @@ default 1 title 启动 efi 文件 chainloader /efi/boot/grub2x64.efi +title 启动 windows +chainloader /efi/microsoft/boot/bootmgfw.efi + title 启动虚拟光盘 find --set-root /cdrom.iso map /cdrom.iso (0xff) diff --git a/stage2/asm.S b/stage2/asm.S index f1c99738..bcbd5aef 100644 --- a/stage2/asm.S +++ b/stage2/asm.S @@ -156,8 +156,13 @@ VARIABLE(min_con_mem_size) //0x82 . = EXT_C(main) + 0x70 //0x8270 uefi未使用 .word 0 - .byte 0 +#if defined(__i386__) + .byte 32 //0x8272 bootia32.efi引导 +#else + .byte 64 // bootx64.efi引导 +#endif + . = EXT_C(main) + 0x73 VARIABLE(debug_msg) //byte .byte 2 @@ -312,7 +317,7 @@ VARIABLE(debug) //调试 int * if debug == MAX_UINT or debug < 0, then filesystem debug mode is on. //如果调试=MAX_UINT或调试<0,那么文件系统调试模式开。 * (MAX_UINT is 0x7FFFFFFF) */ - .long 0 + .long 1 VARIABLE(current_slice) //0x8334 当前片 int .long 0 @@ -361,17 +366,18 @@ VARIABLE(cdrom_orig) //光盘 . = EXT_C(main) + 0x180 //0x8370 -ENTRY(disk_fragment_map) .space FRAGMENT_MAP_SLOT_SIZE //映射碎片插槽 +ENTRY(disk_fragment_map) .space FRAGMENT_MAP_SLOT_SIZE //映射碎片插槽 280 . = EXT_C(main) + 0x400 //0x8670 -ENTRY(disk_buffer) .space 0x1000 //磁盘缓存 +//ENTRY(disk_buffer) .space 0x1000 //磁盘缓存 - . = EXT_C(main) + 0x1400 //0x9600 +// . = EXT_C(main) + 0x1400 //0x9600 ENTRY(disk_drive_map) .space [DRIVE_MAP_SIZE + 1] * DRIVE_MAP_SLOT_SIZE //磁盘驱动器映射插槽 78*8=3c0 - . = EXT_C(main) + 0x1800 +// . = EXT_C(main) + 0x1800 + . = EXT_C(main) + 0x800 real_codestart: .align 8 @@ -612,7 +618,7 @@ VARIABLE(system_functions) //IMG(0x8300) .extent ABS(EXT_C(find_command)) //46 .extent 0 //47 reserved .extent 0 //48 reserved - .extent 0 //49 原ABS(EXT_C(get_mmap_entry)) 现在未使用 + .extent ABS(EXT_C(grub_zalloc)) //49 .extent ABS(EXT_C(grub_malloc)) //50 .extent ABS(EXT_C(grub_free)) //51 .extent 0 //52 原list_partitions 现在未使用 @@ -710,7 +716,7 @@ VARIABLE(current_term) .extent NUM_FSYS //22 常数 VARIABLE(graphics_inited) //23 int .extent 0 - .extent 0 //24 reserved + .extent ABS(EXT_C(BASE_ADDR)) //24 char * //VARIABLE(font8x16) //25 reserved .extent 0 VARIABLE(fontx) //26 int diff --git a/stage2/builtins.c b/stage2/builtins.c index fc6834bc..4eccb798 100644 --- a/stage2/builtins.c +++ b/stage2/builtins.c @@ -51,7 +51,7 @@ int fallback_entries[MAX_FALLBACK_ENTRIES]; int current_entryno; #ifdef SUPPORT_GFX /* graphics file */ -char graphics_file[64]; +//char graphics_file[64]; #endif /* The address for Multiboot command-line buffer. */ static char *mb_cmdline;// = (char *) MB_CMDLINE_BUF; @@ -127,6 +127,8 @@ unsigned long long *next_partition_offset; unsigned int *next_partition_entry; unsigned int *next_partition_ext_offset; char *next_partition_buf; +unsigned char partition_signature[16]; //分区签名 +unsigned char partition_activity_flag; //分区活动标志 int fsys_type; extern unsigned int fats_type; extern unsigned int iso_type; @@ -231,8 +233,6 @@ static unsigned long long blklst_num_sectors; static unsigned int blklst_num_entries; static unsigned int blklst_last_length; -static void disk_read_blocklist_func (unsigned long long sector, unsigned int offset, unsigned long long length); - /* Collect contiguous blocks into one entry as many as possible, and print the blocklist notation on the screen. */ static void disk_read_blocklist_func (unsigned long long sector, unsigned int offset, unsigned long long length); @@ -793,7 +793,7 @@ map_to_svbus (grub_efi_physical_address_t address) } //复制碎片插槽 - grub_memmove ((char *)((char *)(grub_size_t)address + 0x110), (char *)&disk_fragment_map, 0x400); + grub_memmove ((char *)((char *)(grub_size_t)address + 0x120), (char *)&disk_fragment_map, 0x400); } static char chainloader_file[256]; @@ -852,11 +852,6 @@ get_efi_cdrom_device_boot_path (int drive) //获得光盘驱动器引导路径 filepos = part_addr * 0x800; //19*800 struct master_and_dos_boot_sector *BS = (struct master_and_dos_boot_sector *) cache; grub_read ((unsigned long long)(grub_size_t)BS, 0x800, 0xedde0d90); - if (!probe_mbr (BS, 0, 1, 0)) //如果存在mbr - { - part_size = probed_total_sectors; - filesystem_type = 0x100; - } if (!probe_bpb(BS)) part_size = probed_total_sectors; @@ -865,6 +860,7 @@ get_efi_cdrom_device_boot_path (int drive) //获得光盘驱动器引导路径 if (part_size < 0xB40) //BLOCK_OF_1_44MB=0xB40*200=168000 part_size = 0xB40; //1.44Mb软盘尺寸 + part_data = 0; grub_free (cache); return 1; @@ -873,13 +869,31 @@ get_efi_cdrom_device_boot_path (int drive) //获得光盘驱动器引导路径 return 0; } +int find_specified_file (int drive, int partition, char* file); +int +find_specified_file (int drive, int partition, char* file) +{ + int val; + int tem_drive = current_drive; + int tem_partition = current_partition; + + sprintf (chainloader_file, "(hd%d,%d)%s", drive & 0x7f, partition >> 16, file); + putchar_hooked = (unsigned char*)1; //不打印ls_func信息 + val = ls_func (chainloader_file, 1); + putchar_hooked = 0; + current_partition = tem_partition; + current_drive = tem_drive; + + return val; +} + int get_efi_hd_device_boot_path (int drive); int -get_efi_hd_device_boot_path (int drive) //获得光盘驱动器引导路径 +get_efi_hd_device_boot_path (int drive) //获得硬盘驱动器引导路径 { - int tem_drive; struct grub_part_data *p; char *cache = 0; + int self_locking = 0; cache = grub_zalloc (0x800); //分配缓存 if (!cache) @@ -890,24 +904,30 @@ get_efi_hd_device_boot_path (int drive) //获得光盘驱动器引导路径 if (p->drive != drive) continue; - sprintf (chainloader_file, "(hd%d,%d)%s", drive, p->partition >> 16, EFI_REMOVABLE_MEDIA_FILE_NAME); - tem_drive = drive; - putchar_hooked = (unsigned char*)1; //不打印ls_func信息 - if (ls_func (chainloader_file, 1) == 1) //搜索文件 bootx64.efi - { - putchar_hooked = 0; //恢复打印信息 - boot_entry = (grub_efi_uint64_t)(grub_size_t)p; - part_addr = p->partition_start; - part_size = p->partition_len; - grub_free (cache); - return 1; - } - putchar_hooked = 0; //恢复打印信息 - drive = tem_drive; + if (p->partition_type != 0xee && !self_locking) //如果是MBR分区类型, 首先启动活动分区 + { + struct grub_part_data *p_back = p; + while (p && p->drive == drive && p->partition_activity_flag == 0) //查找活动分区 + p = p->next; + if (p && find_specified_file(drive, p->partition, EFI_REMOVABLE_MEDIA_FILE_NAME) == 1) //搜索文件 bootx64.efi + goto complete; + p = p_back; + self_locking = 1; + } + + if (find_specified_file(drive, p->partition, EFI_REMOVABLE_MEDIA_FILE_NAME) == 1) //搜索文件 bootx64.efi + goto complete; } grub_free (cache); return 0; + +complete: + part_data = p; + part_addr = p->partition_start; + part_size = p->partition_len; + grub_free (cache); + return 1; } static void *linuxefi_mem; @@ -974,6 +994,8 @@ boot_func (char *arg, int flags) else { map_to_svbus(grub4dos_self_address); //为svbus复制插槽 + //不能释放,否则无法启动 + //grub_efi_fini (); printf_debug ("StartImage: %x\n", image_handle); //开始映射 status = efi_call_3 (b->start_image, image_handle, 0, NULL); //启动映像 printf_debug ("StartImage returned 0x%lx\n", (grub_size_t) status); //开始映射返回 @@ -992,6 +1014,10 @@ static struct builtin builtin_boot = "with option \"-1\" will boot to local via INT 18.", }; +static grub_efi_char16_t *cmdline; +static grub_ssize_t cmdline_len; +static grub_efi_device_path_t *file_path_public; +static grub_efi_handle_t dev_handle; /* chainloader */ static int chainloader_func (char *arg, int flags); @@ -1005,10 +1031,8 @@ chainloader_func (char *arg, int flags) b = grub_efi_system_table->boot_services; //引导服务 static grub_efi_physical_address_t address; static grub_efi_uintn_t pages; - static grub_efi_char16_t *cmdline; struct grub_disk_data *d; //磁盘数据 - grub_efi_device_path_t *file_path; - int k; + struct grub_part_data *p; set_full_path(chainloader_file,arg,sizeof(chainloader_file)); //设置完整路径(补齐驱动器号,分区号) /efi/boot/bootx64.efi -> (hd0,0)/efi/boot/bootx64.efi chainloader_file[255]=0; @@ -1027,27 +1051,30 @@ chainloader_func (char *arg, int flags) if (*filename == '+') *filename = 0; - if (! *filename) //虚拟盘类型 + //虚拟盘类型 + if (! *filename) { - if (current_partition != 0xFFFFFF) //安装分区 + if (current_partition != 0xFFFFFF) //如果指定启动分区 { - get_efi_hd_device_boot_path (current_drive); //获得光盘驱动器引导路径 - - no_install_vdisk = 1; //0/1=安装虚拟磁盘/不安装虚拟磁盘 - grub_sprintf (chainloader_file, "(0x%X)0x%lX+0x%lX (fd)", current_drive, part_addr, part_size); - k = map_func (chainloader_file, flags); - no_install_vdisk = 0; - grub_close (); - d = get_device_by_drive (current_drive); - vpart_install (k >> 8, d->device_path, (struct grub_part_data*)(grub_size_t)boot_entry); //安装虚拟分区 - d = get_device_by_drive (k & 0xff); - image_handle = vpart_load_image (d->handle); //虚拟磁盘启动 + p = get_partition_info (current_drive, current_partition); //获取分区信息 + if (!p) //没有指定的分区 + { + image_handle = vdisk_load_image (current_drive); //虚拟磁盘启动 + goto complete; + } + + image_handle = vpart_load_image (p->part_path); //虚拟磁盘启动 if (!image_handle) image_handle = vdisk_load_image (current_drive); //虚拟磁盘启动 } - else - image_handle = vdisk_load_image (current_drive); //虚拟磁盘启动 + else //如果没有指定启动分区, 一般是刚安装了分区 + { + image_handle = vpart_load_image (part_data->part_path); //虚拟磁盘启动 + if (!image_handle) + image_handle = vdisk_load_image (current_drive); //虚拟磁盘启动 + } +complete: if (debug > 1) { grub_efi_loaded_image_t *image0 = grub_efi_get_loaded_image (image_handle); //通过映像句柄,获得加载映像 @@ -1057,10 +1084,10 @@ chainloader_func (char *arg, int flags) return 1; } - //打开文件 + //文件类型 grub_open (arg); if (errnum) - goto failure_exec_format; + goto failure_exec_format_0; errnum = ERR_NONE; pages = ((filemax + ((1 << 12) - 1)) >> 12); //计算页 @@ -1080,38 +1107,30 @@ chainloader_func (char *arg, int flags) printf_errinfo ("premature end of file %s",arg); goto failure_exec_format; } + + p = get_partition_info (current_drive, current_partition); + dev_handle = p->part_handle; + + if (! p->part_path) + { + d = get_device_by_drive (current_drive); + dev_handle = d->device_handle; + file_path_public = grub_efi_file_device_path (d->device_path, filename); + } + else + file_path_public = grub_efi_file_device_path (p->part_path, filename); - d = get_device_by_drive (current_drive); - file_path = grub_efi_file_device_path (d->device_path, filename); if (debug > 1) - grub_efi_print_device_path (file_path); //打印设备路径 + grub_efi_print_device_path (file_path_public); //打印设备路径 - status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path, - boot_image, filemax, - &image_handle); //调用(装载镜像,0,镜像句柄,文件路径,引导镜像,尺寸,镜像句柄地址) - - if (status != GRUB_EFI_SUCCESS) //失败退出 - { - if (status == GRUB_EFI_OUT_OF_RESOURCES) - printf_errinfo ("out of resources"); //"资源不足" - else - printf_errinfo ("cannot load image"); //"不能装载镜像" - goto failure_exec_format; - } - - grub_efi_loaded_image_t *image1 = grub_efi_get_loaded_image (image_handle); //通过映像句柄,获得加载映像 - image1->device_handle = d->handle; - printf_debug ("image=0x%x device_handle=%x",image1,d->handle);//113b8e40,11b3d398 - arg = skip_to(0,arg); //标记=0/1/100/200=跳过"空格,回车,换行,水平制表符"/跳过等号/跳到下一行/使用'0'替换 if (*arg) //如果有变量 { - int len = 0; grub_efi_char16_t *p16; - len += grub_strlen ((const char*)arg) + 1; - len *= sizeof (grub_efi_char16_t); - cmdline = p16 = grub_malloc (len); + cmdline_len = grub_strlen ((const char*)arg) + 1; + cmdline_len *= sizeof (grub_efi_char16_t); + cmdline = p16 = grub_malloc (cmdline_len); if (! cmdline) goto failure_exec_format; @@ -1123,13 +1142,33 @@ chainloader_func (char *arg, int flags) *(p16++) = ' '; *(--p16) = 0; - - image1->load_options = cmdline; //加载选项 - image1->load_options_size = len;//加载选项尺寸 } - grub_close (); //关闭文件 + status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path_public, + boot_image, filemax, + &image_handle); //调用(装载镜像,0,镜像句柄,文件路径,引导镜像,尺寸,镜像句柄地址) + if (status != GRUB_EFI_SUCCESS) //失败退出 + { + if (status == GRUB_EFI_OUT_OF_RESOURCES) + printf_errinfo ("out of resources"); //"资源不足" + else + printf_errinfo ("cannot load image"); //"不能装载镜像" + goto failure_exec_format; + } + + grub_efi_loaded_image_t *image1 = grub_efi_get_loaded_image (image_handle); //通过映像句柄,获得加载映像 + //UEFI固件已经设置了“image1->device_handle = d->handle”。他没有分区信息,启动不了某些bootmgfw.efi。必须在此填充对应分区的句柄。 +// d = get_device_by_drive (current_drive); +// image1->device_handle = d->handle; + image1->device_handle = dev_handle; + if (cmdline) + { + image1->load_options = cmdline; //加载选项 + image1->load_options_size = cmdline_len;//加载选项尺寸 + } + printf_debug ("image=0x%x device_handle=%x",image1,dev_handle);//113b8e40,11b3d398 + grub_close (); //关闭文件 kernel_type = KERNEL_TYPE_CHAINLOADER; return 1; @@ -1137,6 +1176,8 @@ chainloader_func (char *arg, int flags) failure_exec_format: grub_close (); + +failure_exec_format_0: if (errnum == ERR_NONE) errnum = ERR_EXEC_FORMAT; @@ -1168,7 +1209,6 @@ static struct builtin builtin_chainloader = " skipped when loading." }; - /* This function could be used to debug new filesystem code. Put a file in the new filesystem and the same file in a well-tested filesystem. Then, run "cmp" with the files. If no output is obtained, probably @@ -2803,6 +2843,10 @@ displaymem_func (char *arg, int flags) grub_efi_uintn_t desc_size; grub_efi_memory_descriptor_t *memory_map; grub_efi_memory_descriptor_t *desc; + grub_efi_status_t status; //状态 + grub_efi_boot_services_t *b; + b = grub_efi_system_table->boot_services; //系统表->引导服务 + int mm_status; //分配内存状态=1/0/-1=成功/部分/失败 int i, mode = 0; if (grub_memcmp (arg, "-s", 2) == 0) //以扇区数计, 简约模式 @@ -2814,7 +2858,28 @@ displaymem_func (char *arg, int flags) else //以字节计, 简约模式(默认) mode = 0; - memory_map = grub_malloc (0x3000); +// memory_map = grub_malloc (0x3000); + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, + GRUB_EFI_LOADER_CODE, mmap_size >> 11, (grub_efi_physical_address_t *)&memory_map); //调用(分配页面,分配类型->任意页面,存储类型->装载程序代码(1),分配页,地址) + if (status) //如果失败 + printf_errinfo ("cannot allocate memory\n"); //无法分配内存 + + mm_status = grub_efi_get_memory_map (&mmap_size, memory_map, 0, &desc_size, 0); //获得内存映射(映射尺寸,映射页,0,描述尺寸,0) 返回1/0/-1=成功/部分/失败 + //获得内存描述符尺寸desc_size, 获得可用内存描述符集地址偏移map_size + if (mm_status == 0) //如果是部分 + { + efi_call_2 (b->free_pages, (grub_efi_physical_address_t)(grub_size_t)memory_map, mmap_size >> 11); //(释放页,地址,页) + mmap_size += desc_size * 32; //增大内存尺寸 + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, + GRUB_EFI_LOADER_CODE, mmap_size >> 11, (grub_efi_physical_address_t *)&memory_map); //调用(分配页面,分配类型->任意页面,存储类型->装载程序代码(1),分配页,地址) + if (! memory_map) //如果失败 + printf_errinfo ("cannot allocate memory\n"); //无法分配内存 + + mm_status = grub_efi_get_memory_map (&mmap_size, memory_map, 0, &desc_size, 0); //获得内存映射 + } + + if (mm_status < 0) //如果失败 + printf_errinfo ("cannot get memory map\n"); //无法分配内存 grub_efi_get_memory_map (&mmap_size, memory_map, 0, &desc_size, 0); @@ -2851,7 +2916,8 @@ displaymem_func (char *arg, int flags) && desc->num_pages >= blklst_num_sectors) //答疑等于指定内存 { blklst_num_sectors = desc->physical_start; //返回内存起始地址 - grub_free (memory_map); +// grub_free (memory_map); + efi_call_2 (b->free_pages, (grub_efi_physical_address_t)(grub_size_t)memory_map, mmap_size >> 11); //(释放页,地址,页) return 1; } else @@ -2859,7 +2925,8 @@ displaymem_func (char *arg, int flags) } } - grub_free (memory_map); +// grub_free (memory_map); + efi_call_2 (b->free_pages, (grub_efi_physical_address_t)(grub_size_t)memory_map, mmap_size >> 11); //(释放页,地址,页) return 1; } @@ -3299,10 +3366,10 @@ command_func (char *arg, int flags) arg -= 6; } /* open the command file. */ - char *filename = arg; + char *filename = arg; //文件名: g4e_wb abcdef char file_path[512]; - unsigned int arg_len = grub_strlen(arg);/*get length for build psp */ - char *cmd_arg = skip_to(SKIP_WITH_TERMINATE,arg);/* get argument of command */ + unsigned int arg_len = grub_strlen(arg);/*get length for build psp */ //文件名尺寸 d + char *cmd_arg = skip_to(SKIP_WITH_TERMINATE,arg);/* get argument of command */ //命令参数: abcdef p_exec = NULL; switch(command_open(filename,0)) @@ -3350,21 +3417,21 @@ command_func (char *arg, int flags) unsigned int prog_len; char *program; char *tmp; - prog_len = filemax; - psp_len = ((arg_len + strlen(file_path)+ 16) & ~0xF) + 0x10 + 0x20; - tmp = (char *)grub_malloc(prog_len + 4096 + 16 + psp_len); + prog_len = filemax; //程序(文件)尺寸 + psp_len = ((arg_len + strlen(file_path)+ 16) & ~0xF) + 0x10 + 0x20; //psp尺寸 + tmp = (char *)grub_malloc(prog_len + 4096 + 16 + psp_len); //缓存 if (tmp == NULL) { goto fail; } - program = (char *)((grub_size_t)(tmp + 4095) & ~4095); /* 4K align the program */ - psp = (char *)((grub_size_t)(program + prog_len + 16) & ~0x0F); - unsigned long long *end_signature = (unsigned long long *)(program + filemax - (unsigned long long)8); + program = (char *)((grub_size_t)(tmp + 4095) & ~4095); /* 4K align the program 4K对齐程序*/ //程序缓存 + psp = (char *)((grub_size_t)(program + prog_len + 16) & ~0x0F); //psp地址 + unsigned long long *end_signature = (unsigned long long *)(program + filemax - (unsigned long long)8); //程序结束签名地址 if (p_exec == NULL) { - /* read file to buff and check exec signature. */ + /* read file to buff and check exec signature. 读取文件到程序缓存并检查exec签名*/ if ((grub_read ((unsigned long long)(grub_size_t)program, -1ULL, 0xedde0d90) != filemax)) { if (! errnum) @@ -3398,20 +3465,25 @@ command_func (char *arg, int flags) } if (*end_signature == 0xBCBAA7BA03051805ULL) { - if (*(unsigned long long *)(program + prog_len - 0x20) == 0x646E655F6E69616D) /* main_end New Version*/ + if (*(unsigned long long *)(program + prog_len - 0x20) == 0x646E655F6E69616D) //新版本标记 main_end { - char * tmp1; - char * program1; - unsigned int *bss_end = (unsigned int *)(program + prog_len - 0x24); - if (prog_len != *bss_end){ + char * tmp1; //新缓存 + char * program1;//新程序缓存 + unsigned int *bss_end = (unsigned int *)(program + prog_len - 0x24); //bss结束,即程序尾部 + unsigned int *main_start = (unsigned int *)(program + prog_len - 0x40); //主程序起始 +// if (prog_len != *bss_end){ + if (prog_len != (*bss_end - *main_start)) + { grub_free(tmp); - prog_len = *bss_end; - tmp1 = (char *)grub_malloc(prog_len + 4096 + 16 + psp_len); + tmp = 0; +// prog_len = *bss_end; + prog_len = *bss_end - *main_start; + tmp1 = (char *)grub_malloc(prog_len + 4096 + 16 + psp_len); //新缓存 if (tmp1 == NULL) { goto fail; } - program1 = (char *)((grub_size_t)(tmp1 + 4095) & ~4095); /* 4K align the program */ + program1 = (char *)((grub_size_t)(tmp1 + 4095) & ~4095); /* 4K align the program */ //新程序缓存 if (tmp1 != tmp) { grub_memmove (program1, program, filemax); @@ -3425,6 +3497,7 @@ command_func (char *arg, int flags) printf_warning ("\nWarning! The program is outdated!\n"); psp = (char *)grub_malloc(prog_len + 4096 + 16 + psp_len); grub_free(tmp); + tmp = 0; if (psp == NULL) { goto fail; @@ -3798,13 +3871,13 @@ find_func (char *arg, int flags) { current_drive = saved_drive; current_partition = saved_partition; - if ((current_drive < 0x80 || current_drive >= 0xa0) && find_check(filename,builtin1,arg,flags) == 1) + if (((current_drive < 0x80 && floppies_orig) || (current_drive >= 0xa0 && cdrom_orig)) && find_check(filename,builtin1,arg,flags) == 1) { got_file = 1; if (set_root) goto found; } - else if (current_drive >= 0x80 && current_drive <= 0x8f) + else if (current_drive >= 0x80 && current_drive <= 0x8f && harddrives_orig) { struct grub_part_data *dp; for (dp = partition_info; dp; dp = dp->next) @@ -3847,7 +3920,7 @@ find_func (char *arg, int flags) #endif case 'c':/*Only search first cdrom*/ d = cd_devices; - for ( ; d; d = d->next) //从设备结构起始查; 只要设备存在,并且驱动器号不为零; + for ( ; d && cdrom_orig; d = d->next) //从设备结构起始查; 只要设备存在,并且驱动器号不为零; { current_drive = d->drive; if (tmp_drive == current_drive) @@ -3876,7 +3949,7 @@ find_func (char *arg, int flags) break; case 'f': d = fd_devices; - for ( ; d; d = d->next) //从设备结构起始查; 只要设备存在,并且驱动器号不为零; + for ( ; d && floppies_orig; d = d->next) //从设备结构起始查; 只要设备存在,并且驱动器号不为零; { current_drive = d->drive; if (tmp_drive == current_drive) @@ -6077,13 +6150,15 @@ fragment_map_slot_find(struct fragment_map_slot *q, unsigned int from) //在碎 return 0; } -grub_efi_uint64_t signature; grub_efi_uint64_t part_addr; grub_efi_uint64_t part_size; grub_efi_uint64_t boot_entry; +struct grub_part_data *part_data; unsigned int map_image_HPC, map_image_SPT; grub_efi_device_path_protocol_t* grub_efi_create_device_node (grub_efi_uint8_t node_type, grub_efi_uintn_t node_subtype, grub_efi_uint16_t node_length); +unsigned long long tmp; +int pause_func (char *arg, int flags); /* map */ /* Map FROM_DRIVE to TO_DRIVE. 映射 FROM 驱动器到 TO 驱动器*/ @@ -6098,8 +6173,8 @@ map_func (char *arg, int flags) //对设备进行映射 返回: 0/1=失败/成 char *filename; char *p; struct fragment_map_slot *q; - unsigned int extended_part_start; - unsigned int extended_part_length; +// unsigned int extended_part_start; +// unsigned int extended_part_length; int err; int prefer_top = 0; @@ -6108,15 +6183,15 @@ map_func (char *arg, int flags) //对设备进行映射 返回: 0/1=失败/成 unsigned long long mem = -1ULL; //0=加载到内存 -1=不加载到内存 int read_only = 0; //只读 若read_Only=1,则同时unsafe_boot=1 - unsigned long long sectors_per_track = -1ULL; - unsigned long long heads_per_cylinder = -1ULL; - int add_mbt = -1; +// unsigned long long sectors_per_track = -1ULL; +// unsigned long long heads_per_cylinder = -1ULL; +// int add_mbt = -1; /* prefer_top now means "enable blocks above address of 4GB". prefere_top 意思是“启用高于4GB地址的块”。 * By default, prefer_top = 0, meaning that only 32-bit addressable 默认情况下,prefere_top=0,这意味着指定的虚拟内存驱动器只允许32位可寻址内存。 * memory is allowed for the specified virtual mem-drive. -- tinybit 2017-01-24 */ unsigned long long skip_sectors = 0; - unsigned long long max_sectors = -1ULL; +// unsigned long long max_sectors = -1ULL; filesystem_type = -1; start_sector = sector_count = 0; map_image_HPC = 0; map_image_SPT = 0; @@ -6133,7 +6208,7 @@ map_func (char *arg, int flags) //对设备进行映射 返回: 0/1=失败/成 if (grub_memcmp (arg, "--status", 8) == 0) //1. 状况 按扇区显示 { int byte = 0; - unsigned long long tmp; +// unsigned long long tmp; arg += 8; if (grub_memcmp (arg, "-byte", 5) == 0) //按字节显示 byte = 1; @@ -6296,7 +6371,7 @@ struct drive_map_slot } else if (grub_memcmp (arg, "--ram-drive=", 12) == 0) //8. 内存盘 设置rd驱动器号,默认0x7f,设置区间:0-0xfe { - unsigned long long tmp; +// unsigned long long tmp; p = arg + 12; if (! safe_parse_maxint (&p, &tmp)) return 0; @@ -6308,7 +6383,7 @@ struct drive_map_slot } else if (grub_memcmp (arg, "--rd-base=", 10) == 0) //9. rd基址 { - unsigned long long tmp; +// unsigned long long tmp; p = arg + 10; if (! safe_parse_maxint_with_suffix (&p, &tmp, 9)) return 0; @@ -6318,7 +6393,7 @@ struct drive_map_slot } else if (grub_memcmp (arg, "--rd-size=", 10) == 0) //10. rd尺寸 { - unsigned long long tmp; +// unsigned long long tmp; p = arg + 10; if (! safe_parse_maxint_with_suffix (&p, &tmp, 9)) return 0; @@ -6335,6 +6410,7 @@ struct drive_map_slot } else if (grub_memcmp (arg, "--top", 5) == 0) //21. 内存映射置顶 { + //有人反映:UEFI固件不会自动分配内存到4GB以上,必须强制加载到4GB以上内存。 prefer_top = 1; mem = 0; } @@ -6350,6 +6426,7 @@ struct drive_map_slot { // return 1; } +#if 0 else if (grub_memcmp (arg, "--add-mbt=", 10) == 0) //33. 增加存储块 -1,0,1 { unsigned long long num; @@ -6360,6 +6437,7 @@ struct drive_map_slot if (add_mbt < -1 || add_mbt > 1) return 0; } +#endif else if (grub_memcmp (arg, "--skip-sectors=", 15) == 0) //34. 跳过扇区 { p = arg + 15; @@ -6425,10 +6503,10 @@ struct drive_map_slot /* when whole drive is mapped, the mem option should not be specified. //当映射整体驱动器时,mem选项应当没有指定. * but when we delete a drive map slot, the mem option means force. //但是当我们删除驱动器映像插槽时,mem选项意味着强制. */ - if (mem != -1ULL && to != from) //如果加载到内存,并且to不等于from //mem=0/-1=加载到内存/不加载到内存 - return ! (errnum = ERR_SPECIFY_MEM); //则返回错误 不应该指定内存 - sectors_per_track = 1;/* 1 means the specified geometry will be ignored. */ //每磁道扇区数=1,意味着指定几何探测将被忽略。 - heads_per_cylinder = 1;/* can be any value but ignored since #sectors==1. */ //每柱面磁头数=1,可以是任何值,但被忽略了因为每磁道扇区数=1。 +// if (mem != -1ULL && to != from) //如果加载到内存,并且to不等于from //mem=0/-1=加载到内存/不加载到内存 +// return ! (errnum = ERR_SPECIFY_MEM); //则返回错误 不应该指定内存 +// sectors_per_track = 1;/* 1 means the specified geometry will be ignored. */ //每磁道扇区数=1,意味着指定几何探测将被忽略。 +// heads_per_cylinder = 1;/* can be any value but ignored since #sectors==1. */ //每柱面磁头数=1,可以是任何值,但被忽略了因为每磁道扇区数=1。 /* Note: if the user do want to specify geometry for whole drive map, then * use a command like this: //注意: 如果用户不希望指定几何探测整个驱动器映射,则使用命令行: 使每磁道扇区数>1 * @@ -6441,18 +6519,22 @@ struct drive_map_slot } } - if (mem == -1ULL) //如果不加载到内存 判断是否连续(填充碎片信息) + //判断是否连续(填充碎片信息) + query_block_entries = -1; /* query block list only 仅请求块列表*/ + blocklist_func (to_drive, flags); //请求块列表 执行成功后,将设置query_block_entries=1,设置errnum=0 + if (errnum) + return 0; + if (query_block_entries <= 0 && mem == -1ULL) //如果是动态VHD,不加载到内存 + { + pause_func ("--wait=5 Dynamic VHD needs to be loaded into memory.",1); +// printf_errinfo("Dynamic VHD needs to be loaded into memory.\n"); + return 0; + } + if (query_block_entries > DRIVE_MAP_FRAGMENT && mem == -1ULL) //碎片太多,不加载到内存 + return ! (errnum = ERR_MANY_FRAGMENTS); +#if 0 + if (mem == -1ULL) //如果不加载到内存 { - query_block_entries = -1; /* query block list only 仅请求块列表*/ - blocklist_func (to_drive, flags); //请求块列表 执行成功后,将设置query_block_entries=1,设置errnum=0 -// blocklist_func (to, flags); - - if (errnum) - return 0; - - if (query_block_entries <= 0 || query_block_entries > DRIVE_MAP_FRAGMENT) - return ! (errnum = ERR_MANY_FRAGMENTS); - start_sector = map_start_sector[0]; //此处将扇区计数,更改为按每扇区0x200字节计的小扇区!!! // sector_count = (filemax + 0x1ff) >> SECTOR_BITS; /* in small 512-byte sectors */ @@ -6462,6 +6544,7 @@ struct drive_map_slot if (start_sector == part_start && part_start && sector_count == 1) //如果起始扇区=分区起始,并且分区起始不为零,并且扇区计数=1 sector_count = part_length; //则扇区计数=分区长度 } +#endif cache = grub_zalloc (0x800); //分配缓存 if (!cache) return 0; @@ -6506,7 +6589,7 @@ struct drive_map_slot if (err != SECTOR_SIZE && from != ram_drive) //如果错误号不是0x200,并且from不是rd { - grub_close (); //则关闭 +// grub_close (); //则关闭 /* This happens, if the file size is less than 512 bytes. 如果文件尺寸小于512字节,将发生*/ if (errnum == ERR_NONE) //如果错误号是0 errnum = ERR_EXEC_FORMAT; //则设置错误号为ram_drive @@ -6547,14 +6630,14 @@ struct drive_map_slot errnum = ERR_BAD_ARGUMENT; goto fail_free; } - if (sector_count > max_sectors) //如果扇区计数>最大扇区 - sector_count = max_sectors; //则扇区计数=最大扇区 +// if (sector_count > max_sectors) //如果扇区计数>最大扇区 +// sector_count = max_sectors; //则扇区计数=最大扇区 } //如果(文件最大>=跳过扇区*0x200,并且(文件最大-跳过扇区*0x200)<512),或者引导签名不是0xAA55 - if ((filemax >= (skip_sectors << 9 ) && filemax - (skip_sectors << 9) < 512) || BS->boot_signature != 0xAA55) - goto geometry_probe_failed; //转到几何探测失败 - +// if ((filemax >= (skip_sectors << 9 ) && filemax - (skip_sectors << 9) < 512) || BS->boot_signature != 0xAA55) +// goto geometry_probe_failed; //转到几何探测失败 +#if 0 /* probe the BPB */ //首先探测to驱动器的BPB if (probe_bpb(BS)) //如果没有bpb @@ -6617,11 +6700,11 @@ struct drive_map_slot sector_count = extended_part_length; //扇区计数=扩展分区长度 /* when emulating a hard disk using a logical partition, the geometry should not be specified. 仿真硬盘使用逻辑分区时,几何不应当指定*/ - if ((long long)heads_per_cylinder > 0 || (long long)sectors_per_track > 0) //如果每柱面磁头>0,或者每磁道扇区>0 - { - errnum = ERR_SPECIFY_GEOM; //则返回错误 - goto fail_free; - } +// if ((long long)heads_per_cylinder > 0 || (long long)sectors_per_track > 0) //如果每柱面磁头>0,或者每磁道扇区>0 +// { +// errnum = ERR_SPECIFY_GEOM; //则返回错误 +// goto fail_free; +// } goto failed_probe_BPB; //转到探测bpb失败 } @@ -6642,7 +6725,7 @@ struct drive_map_slot //几何探测成功 geometry_probe_ok: - + if (mem != -1ULL && ((long long)mem) <= 0) //如果加载到内存,并且mem<=0 { //如果-mem<探测总扇区,并且探测总扇区>1,并且扇区计数>=1 @@ -6652,7 +6735,7 @@ struct drive_map_slot //映射整体驱动器 map_whole_drive: - +#endif if (from != ram_drive) //如果from不等于rd { /* Search for an empty slot in disk_drive_map. 在磁盘驱动器映射中搜索空插槽*/ @@ -6697,6 +6780,7 @@ struct drive_map_slot (sector_count == 1))) { grub_free (cache); + cache = 0; goto delete_drive_map_slot; //删除驱动器映像插槽 } } @@ -6726,7 +6810,8 @@ struct drive_map_slot { //如果是整体映射 - if (start_sector == 0 && (sector_count == 0 || (sector_count == 1 && (long long)heads_per_cylinder <= 0 && (long long)sectors_per_track <= 1))) +// if (start_sector == 0 && (sector_count == 0 || (sector_count == 1 && (long long)heads_per_cylinder <= 0 && (long long)sectors_per_track <= 1))) + if (start_sector == 0 && (sector_count == 0 || sector_count == 1)) { sector_count = disk_drive_map[j].sector_count; //扇区计数=父扇区计数 } @@ -6843,18 +6928,19 @@ struct drive_map_slot } get_info_ok: - grub_free (cache); + cache = 0; //==================================================================================================================== /* how much memory should we use for the drive emulation? */ if (mem != -1ULL) //如果加载到内存 { unsigned long long start_byte; //起始字节 unsigned long long bytes_needed; //需要字节 - unsigned long long base; //基地址 - unsigned long long top_end; //顶端 +// unsigned long long base; //基地址 +// unsigned long long top_end; //顶端 - bytes_needed = base = top_end = 0ULL; //初始化: 需要字节=基地址=顶端=0 +// bytes_needed = base = top_end = 0ULL; //初始化: 需要字节=基地址=顶端=0 + bytes_needed = 0ULL; //初始化: 需要字节=基地址=顶端=0 if (start_sector == part_start && part_start == 0 && sector_count == 1) //如果起始扇区=分区起始,并且分区起始=0,并且扇区计数=1 sector_count = part_length; //扇区计数=分区长度 @@ -6876,12 +6962,12 @@ struct drive_map_slot * Note: An MBR device is a whole disk image that has a partition table. */ - if (add_mbt<0) //如果=-1,没有输入参数 - add_mbt = (filesystem_type > 0 && (from & 0x80) && (from < 0x9F))? 1: 0; /* known filesystem without partition table */ +// if (add_mbt<0) //如果=-1,没有输入参数 +// add_mbt = (filesystem_type > 0 && (from & 0x80) && (from < 0x9F))? 1: 0; /* known filesystem without partition table */ //增加分配块=1/0=(filesystem_type>0,并且from是硬盘/否则 无分区表的已知文件系统 - if (add_mbt) //如果增加分配块=1, 需要字节+每磁道扇区数*0x200 - bytes_needed += sectors_per_track << SECTOR_BITS; /* build the Master Boot Track */ +// if (add_mbt) //如果增加分配块=1, 需要字节+每磁道扇区数*0x200 +// bytes_needed += sectors_per_track << SECTOR_BITS; /* build the Master Boot Track */ bytes_needed = ((bytes_needed+4095)&(-4096ULL)); /* 4KB alignment 4k对齐*/ @@ -6950,7 +7036,8 @@ struct drive_map_slot if ((to == 0xffff || to == ram_drive) && !compressed_file) //如果映像在内存中,并且没有压缩,我们可以简单地移动它。 { if (bytes_needed != start_byte) //如果需要字节!=起始字节 - grub_memmove64 (disk_drive_map[i].start_sector, start_byte, (max_sectors >= filemax) ? filemax : (sector_count << SECTOR_BITS)); +// grub_memmove64 (disk_drive_map[i].start_sector, start_byte, (max_sectors >= filemax) ? filemax : (sector_count << SECTOR_BITS)); + grub_memmove64 (disk_drive_map[i].start_sector, start_byte, filemax); } else //如果映像不在内存中,或者被压缩 { @@ -6968,6 +7055,7 @@ struct drive_map_slot errnum = ERR_READ; return 0; } + blklst_num_entries = 1; //如果文件有碎片,加载到内存后就连续了。避免后续设置碎片。 } grub_close (); //关闭to驱动器 disk_drive_map[i].start_sector >>= 9; //此处恢复内存起始扇区!!! @@ -6980,10 +7068,12 @@ struct drive_map_slot */ if (from == ram_drive) //如果from是rd { - rd_base = base; //rd基址 - rd_size = (max_sectors >= filemax) ? filemax : (sector_count << 9); - if (add_mbt) //增加存储块=1 - rd_size += sectors_per_track << 9; /* build the Master Boot Track rd长度+每磁道扇区数*0x200*/ +// rd_base = base; //rd基址 + rd_base = start_sector; //rd基址 +// rd_size = (max_sectors >= filemax) ? filemax : (sector_count << 9); + rd_size = filemax; +// if (add_mbt) //增加存储块=1 +// rd_size += sectors_per_track << 9; /* build the Master Boot Track rd长度+每磁道扇区数*0x200*/ return 1; } } //if (mem != -1ULL)结束 //如果加载到内存结束 @@ -7791,7 +7881,6 @@ static struct builtin builtin_password = /* pause */ //static int -int pause_func (char *arg, int flags); int pause_func (char *arg, int flags) { @@ -9818,17 +9907,18 @@ graphicsmode_func (char *arg, int flags) char *x_restrict = "0:-1"; char *y_restrict = "0:-1"; char *z_restrict = "0:-1"; - unsigned int x = 0; /* x_resolution */ - unsigned int y = 0; /* y_resolution */ - unsigned int z = 0; /* bits_per_pixel */ + unsigned int x = 0, x0 = 0; /* x_resolution */ + unsigned int y = 0, y0 = 0; /* y_resolution */ + unsigned int z = 0, z0 = 0; /* bits_per_pixel */ grub_efi_handle_t *handles; grub_efi_uintn_t num_handles; - unsigned int bytes_per_scanline=0, bits_per_pixel; + unsigned int bytes_per_scanline=0, bits_per_pixel, bytes_per_scanline0=0; static struct grub_efi_gop *gop; unsigned int red_mask_size, green_mask_size, blue_mask_size, reserved_mask_size; unsigned int red_field_pos, green_field_pos, blue_field_pos, reserved_field_pos; int mode; static grub_efi_guid_t graphics_output_guid = GRUB_EFI_GOP_GUID; + grub_efi_status_t status; errnum = 0; if (! *arg) @@ -9843,7 +9933,7 @@ graphicsmode_func (char *arg, int flags) char *tmp_arg; tmp_arg = arg = wee_skip_to (arg, 0); - if (! *arg) + if (! *arg) //只有 -1 goto xyz_done; if (! safe_parse_maxint (&arg, &tmp_ll)) goto bad_arg; @@ -9852,7 +9942,7 @@ graphicsmode_func (char *arg, int flags) tmp_arg = arg = wee_skip_to (arg, 0); if (! *arg) - goto xyz_done; + goto xyz_done; //只有 -1 x if (! safe_parse_maxint (&arg, &tmp_ll)) goto bad_arg; if (tmp_ll != -1ULL || (unsigned char)*arg > ' ') @@ -9860,11 +9950,11 @@ graphicsmode_func (char *arg, int flags) tmp_arg = arg = wee_skip_to (arg, 0); if (! *arg) - goto xyz_done; + goto xyz_done; //只有 -1 x y if (! safe_parse_maxint (&arg, &tmp_ll)) goto bad_arg; if (tmp_ll != -1ULL || (unsigned char)*arg > ' ') - z_restrict = tmp_arg; + z_restrict = tmp_arg; //全部 -1 x y z }//if ((unsigned long)tmp_graphicsmode == -1) }//lse if (!safe_parse_maxint (&arg, &tmp_graphicsmode)) else @@ -9888,7 +9978,6 @@ graphicsmode_func (char *arg, int flags) for (mode = gop->mode->max_mode - 1; mode >= 0; mode--) { grub_efi_uintn_t size1; - grub_efi_status_t status; struct grub_efi_gop_mode_info *info = NULL; status = efi_call_4 (gop->query_mode, gop, mode, &size1, &info); //gop查询模式 通过mode查询, 返回模式尺寸及信息 @@ -9949,9 +10038,9 @@ graphicsmode_func (char *arg, int flags) y = _Y_; z = _Z_; bytes_per_scanline = info->pixels_per_scanline * (bits_per_pixel >> 3); - status = efi_call_2 (gop->set_mode, gop, mode); //gop设置模式 - if (status) //失败 - goto bad_arg; +// status = efi_call_2 (gop->set_mode, gop, mode); //gop设置模式 +// if (status) //失败 +// goto bad_arg; break; } else if ((unsigned int)tmp_graphicsmode == (unsigned int)-1 /* mode auto detect */ @@ -9964,15 +10053,35 @@ graphicsmode_func (char *arg, int flags) y = _Y_; z = _Z_; bytes_per_scanline = info->pixels_per_scanline * (bits_per_pixel >> 3); - status = efi_call_2 (gop->set_mode, gop, mode); //gop设置模式 - if (status) //失败 - goto bad_arg; +// status = efi_call_2 (gop->set_mode, gop, mode); //gop设置模式 +// if (status) //失败 +// goto bad_arg; tmp_graphicsmode = 0x100 | mode; break; } + else if (mode == 0) + { + x0 = _X_; + y0 = _Y_; + z0 = _Z_; + bytes_per_scanline0 = info->pixels_per_scanline * (bits_per_pixel >> 3); + } } //for (mode = 0; mode < gop->mode->max_mode; mode++) // }//for (i = 0; i < num_handles; i +#undef _X_ +#undef _Y_ +#undef _Z_ + + if ((unsigned int)tmp_graphicsmode == (unsigned int)-1) + { + tmp_graphicsmode = 0x100; + x = x0; + y = y0; + z = z0; + bytes_per_scanline = bytes_per_scanline0; + } + if (tmp_graphicsmode == 0x2ff) { return graphics_mode; @@ -9987,6 +10096,9 @@ graphicsmode_func (char *arg, int flags) } else if (tmp_graphicsmode > 0xff) { + status = efi_call_2 (gop->set_mode, gop, tmp_graphicsmode & 0xff); //gop设置模式 + if (status) //失败 + goto bad_arg; current_x_resolution = x; current_y_resolution = y; current_bits_per_pixel = z; @@ -9995,9 +10107,6 @@ graphicsmode_func (char *arg, int flags) current_bytes_per_scanline = bytes_per_scanline; current_term->chars_per_line = current_x_resolution / (font_w + font_spacing); current_term->max_lines = current_y_resolution / (font_h + line_spacing); -#undef _X_ -#undef _Y_ -#undef _Z_ if (graphics_mode != (unsigned int)tmp_graphicsmode //如果当前视频模式不是探测图形模式 || current_term != term_table + 1) /* terminal graphics */ //或者当前终端不是图像终端 diff --git a/stage2/common.c b/stage2/common.c index d2cdda04..8b8b699a 100644 --- a/stage2/common.c +++ b/stage2/common.c @@ -556,7 +556,7 @@ get_header_from_pointer (void *ptr, grub_mm_header_t *p, grub_mm_region_t *r) break; if (! *r) - printf_errinfo ("out of range pointer %x\n", ptr); //超出范围指针%x + printf_errinfo ("out of range pointer %x\n", ptr); //指针超出范围 *p = (grub_mm_header_t) ptr - 1; if ((*p)->magic == GRUB_MM_FREE_MAGIC) //魔术 0x2d3c2808 @@ -618,7 +618,7 @@ grub_free (void *ptr) r->first = q; } - ptr = 0; + ptr = 0; //这个值没有传递回去,没有起作用. } /* @@ -927,7 +927,7 @@ struct efi_allocation { struct efi_allocation *next; //下一个 4位 0=结束符 }; static struct efi_allocation *efi_allocated_memory; //0x14位 静态,地址不变 - +#if 0 static void grub_efi_store_alloc (grub_efi_physical_address_t address, grub_efi_uintn_t pages); static void grub_efi_store_alloc (grub_efi_physical_address_t address, @@ -978,7 +978,7 @@ grub_efi_drop_alloc (grub_efi_physical_address_t address, break; } } - +#endif //第一次分配页时,会多分配一页,用于记录分配结构. 似乎每一结构占用0x80字节(实际结构每一这么大).此页不会释放. //分配页后,紧接分配池.并记录分配结构. /* Allocate pages. Return the pointer to the first of allocated pages. 分配页面。返回指向第一个分配页面的指针 */ @@ -1014,7 +1014,7 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, return 0; } - grub_efi_store_alloc (address, pages); //分配池(地址,页) +// grub_efi_store_alloc (address, pages); //分配池(地址,页) return (void *) ((grub_addr_t) address);//返回地址 } @@ -1050,7 +1050,7 @@ grub_efi_free_pages (grub_efi_physical_address_t address, b = grub_efi_system_table->boot_services;//系统表->引导服务 efi_call_2 (b->free_pages, address, pages); //(释放页,地址,页) - grub_efi_drop_alloc (address, pages); //释放池 +// grub_efi_drop_alloc (address, pages); //释放池 } grub_err_t grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf, @@ -1519,7 +1519,6 @@ defer (unsigned short millisecond) efi_call_1 (grub_efi_system_table->boot_services->stall, millisecond * 1000); } - grub_efi_physical_address_t grub4dos_self_address = 0; void copy_grub4dos_self_address (void); void @@ -1542,10 +1541,12 @@ copy_grub4dos_self_address (void) return; //清除残留 grub_memset ((void *)(grub_size_t)grub4dos_self_address, 0, 0x1000); - //复制特定字符串 + //复制特定字符串, 为了SVBus grub_memmove ((void *)(grub_size_t)(grub4dos_self_address + 0xe0), " $INT13SFGRUB4DOS", 19); + //复制特定字符串, 为了G4E外部命令 + grub_memmove ((void *)(grub_size_t)(grub4dos_self_address + 0x100), "GRUB4EFI", 8); //复制bootx64.efi自身地址 - *(grub_size_t*)((char *)(grub_size_t)grub4dos_self_address + 0x100) = (grub_size_t)grub_image; + *(grub_size_t*)((char *)(grub_size_t)grub4dos_self_address + 0x110) = (grub_size_t)grub_image; } char *grub_image; @@ -1564,7 +1565,7 @@ char *BUFFERADDR; char *CMD_RUN_ON_EXIT; char *SCRATCHADDR; char *mbr; -//char * +char *disk_buffer; //char * void grub_console_init (void); @@ -1600,6 +1601,7 @@ grub_init (void) CMD_RUN_ON_EXIT = grub_malloc (256); // SCRATCHADDR = grub_malloc (0x1000); //临时 mbr = grub_malloc (0x1000); //mbr + disk_buffer = grub_malloc (0x1000); //磁盘缓存 //buffer=grub_malloc (byte) 分配内存 //buffer=grub_zalloc (byte) 分配内存, 并清零 //grub_free (buffer) 释放内存 diff --git a/stage2/dec_vhd.c b/stage2/dec_vhd.c index 05bb3e18..1ce0f90c 100644 --- a/stage2/dec_vhd.c +++ b/stage2/dec_vhd.c @@ -27,37 +27,37 @@ #ifndef NO_DECOMPRESSION -typedef struct VHDFooter { - unsigned char cookie[8];//string conectix - grub_u32_t features; - grub_u32_t fileFormatVersion; - grub_u64_t dataOffset; - grub_u32_t timeStamp; - unsigned char creatorApplication[4]; - grub_u32_t creatorVersion; - grub_u32_t creatorHostOS; - grub_u64_t originalSize; - grub_u64_t currentSize; +typedef struct VHDFooter { //VHDṹ + unsigned char cookie[8]; // ַconectix + grub_u32_t features; // + grub_u32_t fileFormatVersion; //ļʽ汾 + grub_u64_t dataOffset; //ƫ + grub_u32_t timeStamp; //ʱ + unsigned char creatorApplication[4]; //Ӧó + grub_u32_t creatorVersion; //߰汾 + grub_u32_t creatorHostOS; //ϵͳ + grub_u64_t originalSize; //ԭʼߴ + grub_u64_t currentSize; //ǰߴ struct { - unsigned short cylinder; - unsigned char heads; - unsigned char sectorsPerTrack; + unsigned short cylinder; // + unsigned char heads; //ͷ + unsigned char sectorsPerTrack; // } diskGeometry; - grub_u32_t diskType; - grub_u32_t checksum; - unsigned char uniqueId[16]; - unsigned char savedState; - unsigned char reserved[427]; + grub_u32_t diskType; // 2̶, 3̬, 4 + grub_u32_t checksum; //У + unsigned char uniqueId[16]; //ΨһId + unsigned char savedState; //״̬ + unsigned char reserved[427]; // } VHDFooter; -#define VHD_FOOTER_COOKIE 0x78697463656E6F63ULL +#define VHD_FOOTER_COOKIE 0x78697463656E6F63ULL //VHDṹ #define VHD_DYNAMIC_COOKIE 0x6573726170737863ULL -#define VHD_DISKTYPE_FIXED 2 -#define VHD_DISKTYPE_DYNAMIC 3 -#define VHD_DISKTYPE_DIFFERENCE 4 +#define VHD_DISKTYPE_FIXED 2 //̶ +#define VHD_DISKTYPE_DYNAMIC 3 //̬ +#define VHD_DISKTYPE_DIFFERENCE 4 // -typedef struct VHDDynamicDiskHeader { +typedef struct VHDDynamicDiskHeader { //VHD̬ͷ unsigned char cookie[8];//string cxsparse grub_u64_t dataOffset; grub_u64_t tableOffset; @@ -75,7 +75,7 @@ typedef struct VHDDynamicDiskHeader { typedef struct VHDFileControl VHDFileControl; -struct VHDFileControl { +struct VHDFileControl { //VHDļ unsigned long long cFileMax; unsigned long long volumeSize; unsigned long long tableOffset; @@ -161,11 +161,14 @@ dec_vhd_close(void) if (vhdfc) { if (vhdfc->blockAllocationTable) { grub_free(vhdfc->blockAllocationTable); + vhdfc->blockAllocationTable = 0; } if (vhdfc->blockBitmapAndData) { grub_free(vhdfc->blockBitmapAndData); + vhdfc->blockBitmapAndData = 0; } grub_free(vhdfc); + vhdfc = 0; map_image_HPC = 0; map_image_SPT = 0; } @@ -180,48 +183,44 @@ dec_vhd_open(void) VHDDynamicDiskHeader dynaheader; if (filemax < 0x10000) return 0;//file is to small - /* Now it does not support openning more than 1 file at a time. - Make sure previously allocated memory blocks is freed. + /* Now it does not support openning more than 1 file at a time. ֧һδ򿪶ļ + Make sure previously allocated memory blocks is freed. ȷǰڴͷš Don't need this line if grub_close is called for every openned file before grub_open is called for next file. */ + //Ϊһļgrub_open֮ǰΪÿ򿪵ļgrub_closeҪС dec_vhd_close(); memset(&footer, 0, sizeof(footer)); memset(&dynaheader, 0, sizeof(dynaheader)); - int bytesread = (int)grub_read((grub_size_t)&footer, 0x200, 0xedde0d90); + int bytesread = (int)grub_read((grub_size_t)&footer, 0x200, 0xedde0d90); //̬VHDʼ1VHDṹ̶VHDĽṹһ bytesread = bytesread; //if (bytesread < 511) { // grub_printf("bytesread %d < 511\n",bytesread); // goto quit; //} grub_u64_t* a = (grub_u64_t*)&footer.cookie; -// if (*(grub_u64_t*)&footer.cookie!=VHD_FOOTER_COOKIE) { - if (*a!=VHD_FOOTER_COOKIE) { - // grub_printf("cookie %lX != %lX\n", footer.cookie, VHD_FOOTER_COOKIE); + if (*a!=VHD_FOOTER_COOKIE) { //VHDṹ,˳ (̶VHD) goto quit; } vhd_footer_in(&footer); - if (footer.diskType != VHD_DISKTYPE_DYNAMIC) { - /* Differencing disk and unknown diskType are not supported */ + if (footer.diskType != VHD_DISKTYPE_DYNAMIC) { //ͲǶ̬, ˳ + /* Differencing disk and unknown diskType are not supported ֲ֧̺δ֪ */ goto quit; } -// if (footer.diskType == VHD_DISKTYPE_DYNAMIC) { - if (footer.dataOffset + sizeof(dynaheader) > filemax) { - // grub_printf("footer dataOffset %lX\n", dataOffset); + if (footer.dataOffset + sizeof(dynaheader) > filemax) { //ƫ+VHDṹ > filemax, ˳ goto quit; } filepos = footer.dataOffset; - bytesread = (int)grub_read((grub_size_t)&dynaheader, sizeof(dynaheader), 0xedde0d90); -// } + bytesread = (int)grub_read((grub_size_t)&dynaheader, sizeof(dynaheader), 0xedde0d90); //VHD̬ͷ vhdfc = (VHDFileControl*) grub_malloc(sizeof(VHDFileControl)); if (!vhdfc) { goto quit; } - + //VHDļ memset(vhdfc, 0, sizeof(VHDFileControl)); vhd_header_in(&dynaheader); vhdfc->cFileMax = filemax; @@ -244,9 +243,9 @@ dec_vhd_open(void) //} map_image_HPC = footer.diskGeometry.heads; map_image_SPT = footer.diskGeometry.sectorsPerTrack; - compressed_file = 1; - decomp_type = DECOMP_TYPE_VHD; - filemax = vhdfc->volumeSize; + compressed_file = 1; //ѹļ + decomp_type = DECOMP_TYPE_VHD; //ѹVHD + filemax = vhdfc->volumeSize; //޸filemax quit: filepos = 0; @@ -285,7 +284,7 @@ dec_vhd_read(unsigned long long buf, unsigned long long len, unsigned int write) bswap_32(&blockLBA); // grub_printf("read bn %x of %x txlen %x lba %x\n", blockNumber, offsetInBlock, txLen, blockLBA); if (blockLBA == 0xFFFFFFFF) { - // unused block on dynamic VHD. read zero + // unused block on dynamic VHD. read zero ̬VHDδʹõĿ顣ȡ0 grub_memset64(buf, 0, txLen); } else { diff --git a/stage2/disk_io.c b/stage2/disk_io.c index 119d639f..86958b3b 100644 --- a/stage2/disk_io.c +++ b/stage2/disk_io.c @@ -679,6 +679,7 @@ static int next_gpt_slice(void) *next_partition_len = (unsigned long long)(PI->ending_lba - PI->starting_lba + 1); *next_partition_partition = (pc_slice_no << 16) | 0xFFFF; *next_partition_type = PC_SLICE_TYPE_GPT; + grub_memmove(&partition_signature, &PI->uid, 16); return 1; } @@ -823,6 +824,9 @@ next_pc_slice (void) *next_partition_start = tmp_start; *next_partition_type = PC_SLICE_TYPE (next_partition_buf, *next_partition_entry); *next_partition_len = PC_SLICE_LENGTH (next_partition_buf, *next_partition_entry); + grub_memset (&partition_signature, 0, 16); + *(unsigned int *)partition_signature = PC_DISK_SIG (next_partition_buf); + partition_activity_flag = PC_SLICE_FLAG(next_partition_buf, *next_partition_entry); /* if overflow ... */ /* use this to keep away from the gcc bug. @@ -2236,6 +2240,8 @@ get_diskinfo (unsigned int drive, struct geometry *geometry, unsigned int partit /* GUID. */ static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID; +struct grub_part_data* partition_info_tmp = 0; + //由枚举磁盘调用 static struct grub_disk_data *make_devices (void); static struct grub_disk_data * @@ -2245,6 +2251,7 @@ make_devices (void) //制作设备 grub_efi_handle_t *handles; //句柄集 api返回 grub_efi_handle_t *handle; //句柄 struct grub_disk_data *devices = 0; + struct grub_part_data *p; //efi分区数据 /* Find handles which support the disk io interface. 查找支持磁盘IO接口的句柄 */ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &block_io_guid, @@ -2261,16 +2268,19 @@ make_devices (void) //制作设备 grub_efi_block_io_t *bio; dp = grub_efi_get_device_path (*handle); //获得设备路径 通过协议 - if (debug > 1) - grub_efi_print_device_path(dp); - if (! dp) //如果失败,继续 continue; + if (debug > 1) + grub_efi_print_device_path(dp); ldp = grub_efi_find_last_device_path (dp); //查找最后设备路径 if (! ldp) //如果失败,继续 - /* This is empty. Why? 这是空的。为什么 */ continue; + if (debug > 1) + { + grub_efi_print_device_path(ldp); + getkey(); + } bio = grub_efi_open_protocol (*handle, &block_io_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); //打开协议 获得协议 块输入输出 @@ -2301,7 +2311,7 @@ make_devices (void) //制作设备 } //填充设备结构 - d->handle = *handle; + d->device_handle = *handle; d->device_path = dp; d->last_device_path = ldp; d->block_io = bio; @@ -2310,7 +2320,22 @@ make_devices (void) //制作设备 d->total_sectors = bio->media->last_block + 1; d->next = devices; devices = d; - } + + //填充分区数据结构 + if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE + && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE) //如果是媒体类型,硬盘子类型 + { + p = grub_malloc (sizeof (*p)); //分配内存 + p->part_handle = *handle; + p->part_path = dp; + p->last_part_path = ldp; + p->partition_start = ((grub_efi_hard_drive_device_path_t *)ldp)->partition_start; + p->partition_len = ((grub_efi_hard_drive_device_path_t *)ldp)->partition_size; + grub_memcpy (&p->partition_signature, &((grub_efi_hard_drive_device_path_t *)ldp)->partition_signature, 16); + p->next = partition_info_tmp; + partition_info_tmp = p; + } + } grub_free (handles); return devices; @@ -2504,7 +2529,7 @@ name_devices (struct grub_disk_data *devices) //命名设备 } } } - +#if 0 //其次,识别其他类型的设备 光驱,软驱等等 /* Let's see what can be added more. 让我们看看可以增加什么 */ for (d = devices; d; d = d->next) @@ -2570,9 +2595,10 @@ name_devices (struct grub_disk_data *devices) //命名设备 grub_efi_print_device_path (d->device_path); //efi打印设备路径 } // add_device (&hd_devices, d); //增加设备->硬盘 - add_device (&fd_devices, d); //增加设备->软盘 + add_device (&fd_devices, d); //增加设备->软盘 实机启动,遇到光驱,死机。 } } +#endif } //由枚举磁盘,efidisk结束,获取设备句柄调用 @@ -2618,6 +2644,16 @@ enumerate_disks (void) //枚举磁盘 name_devices (devices); //命名设备 free_disk_data (devices); //释放 + + struct grub_disk_data *d; //磁盘数据 + int i, j; + //分配驱动器号 + for (i = 0xa0, d = cd_devices, j = cdrom_orig; j; j--, d = d->next, i++) + d->drive = i; + for (i = 0x80, d = hd_devices, j = harddrives_orig; j; j--, d = d->next, i++) + d->drive = i; + for (i = 0, d = fd_devices, j = floppies_orig; j; j--, d = d->next, i++) + d->drive = i; } grub_efi_device_path_t *efi_file_path; @@ -2881,6 +2917,7 @@ void partition_info_init (void) { struct grub_part_data *d; //efi分区数据 + struct grub_part_data *p; int drive; unsigned int back_saved_drive = saved_drive; unsigned int back_current_drive = current_drive; @@ -2898,16 +2935,16 @@ partition_info_init (void) unsigned int type, entry1, ext_offset1; saved_drive = current_drive = drive; saved_partition = current_partition = part; - while (( next_partition_drive = drive, - next_partition_dest = 0xFFFFFF, - next_partition_partition = &part, - next_partition_type = &type, - next_partition_start = &start, - next_partition_len = &len, - next_partition_offset = &offset, - next_partition_entry = &entry1, - next_partition_ext_offset = &ext_offset1, - next_partition_buf = mbr, + while (( next_partition_drive = drive, //驱动器 + next_partition_dest = 0xFFFFFF, //搜索目标分区. 即要查找的分区,找到后结束查询. 若要例遍所有分区,则设置为0xffffff. + next_partition_partition = &part, //当前分区 + next_partition_type = &type, //分区类型 + next_partition_start = &start, //分区起始 + next_partition_len = &len, //分区尺寸 + next_partition_offset = &offset, //分区偏移 扩展分区表位置. 偏移3f扇区即逻辑分区起始. + next_partition_entry = &entry1, //分区入口 对于mbr分区,视乎是主分区标号, 对于gpt分区,视乎都是2. + next_partition_ext_offset = &ext_offset1, //扩展分区偏移 扩展分区表基地址,位于主分区. 所有的扩展分区表的起始地址,都是相对地址. + next_partition_buf = mbr, //缓存 next_partition ())) { d = grub_malloc (sizeof (*d)); //分配内存 @@ -2926,6 +2963,19 @@ partition_info_init (void) d->partition_entry = *next_partition_entry; //2 2 2 2 0 1 2 0 0 0 d->partition_ext_offset = *next_partition_ext_offset; //0 0 0 0 0 0 0 a0029cc a0029cc a0029cc d->next = partition_info; //0 dfb0110 dfb00e0 dfb00b0 dfb0080 dfb0050 dfaff90 dfaff60 + grub_memcpy (&d->partition_signature, &partition_signature, 16); + + //从partition_info_tmp中查找有关信息 + for (p = partition_info_tmp; p; p = p->next) + { + if (p->partition_start == d->partition_start && p->partition_len == d->partition_len) + { + d->part_handle = p->part_handle; + d->part_path = p->part_path; + d->last_part_path = p->last_part_path; + } + } + partition_info = d; //dfb0110 dfb00e0 dfb00b0 dfb0080 dfb0050 dfaff90 dfaff60 dfaff30 } } @@ -2933,6 +2983,7 @@ partition_info_init (void) current_drive = back_current_drive; saved_partition = back_saved_partition; current_partition = back_current_partition; + free_part_data (partition_info_tmp); //释放 } struct grub_part_data *get_partition_info (int drive, int partition); @@ -3185,8 +3236,7 @@ get_mbr_info (int slot_number, grub_efi_device_path_t *dp, struct grub_part_data ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_number = (p->partition >> 16) + 1; //分区号 ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_start = p->partition_start; //分区起始 扇区 ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_size = p->partition_len; //分区尺寸 扇区 - *(grub_efi_uint32_t*)((grub_efi_hard_drive_device_path_t*)tmp_dp) - ->partition_signature = signature; //分区签名 + grub_memmove(&(((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_signature), &(p->partition_signature), 16); //分区签名 ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partmap_type = 1; //分区格式类型 ((grub_efi_hard_drive_device_path_t*)tmp_dp)->signature_type = 1; //签名类型 //附加设备节点 @@ -3217,8 +3267,7 @@ get_gpt_info (int slot_number, grub_efi_device_path_t *dp, struct grub_part_data ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_number = (p->partition >> 16) + 1; //分区号 ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_start = p->partition_start; //分区起始 扇区 ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_size = p->partition_len; //分区尺寸 扇区 - *(grub_efi_uint32_t*)((grub_efi_hard_drive_device_path_t*)tmp_dp) - ->partition_signature = signature; //分区签名 + grub_memmove(&((grub_efi_hard_drive_device_path_t*)tmp_dp)->partition_signature, &p->partition_signature, 16); //分区签名 ((grub_efi_hard_drive_device_path_t*)tmp_dp)->partmap_type = 2; //分区格式类型 ((grub_efi_hard_drive_device_path_t*)tmp_dp)->signature_type = 2; //签名类型 //附加设备节点 @@ -3460,7 +3509,7 @@ vpart_install (int slot_number, grub_efi_device_path_t *dp, struct grub_part_dat d = grub_zalloc (sizeof (*d)); //分配内存, 并清零 struct grub_disk_data *d1; - d->handle = disk_drive_map[slot_number].from_handle; + d->device_handle = disk_drive_map[slot_number].from_handle; d->device_path = disk_drive_map[slot_number].dp; d->last_device_path = 0; d->block_io = (grub_efi_block_io_t *)&disk_drive_map[slot_number].block_io; @@ -3469,6 +3518,8 @@ vpart_install (int slot_number, grub_efi_device_path_t *dp, struct grub_part_dat d->total_sectors = disk_drive_map[slot_number].sector_count; d->drive = disk_drive_map[slot_number].from_drive; d->next = 0; + p->part_handle = d->device_handle; + p->part_path = d->device_path; if (!fd_devices) fd_devices = d; @@ -3483,9 +3534,9 @@ vpart_install (int slot_number, grub_efi_device_path_t *dp, struct grub_part_dat } //获得文件设备路径,加载映像 -grub_efi_handle_t vpart_load_image (grub_efi_handle_t *part_handle); +grub_efi_handle_t vpart_load_image (grub_efi_device_path_t *part_path); grub_efi_handle_t -vpart_load_image (grub_efi_handle_t *part_handle) //虚拟分区引导 +vpart_load_image (grub_efi_device_path_t *part_path) //虚拟分区引导 { grub_efi_status_t status; grub_efi_handle_t boot_image_handle = NULL; @@ -3493,11 +3544,10 @@ vpart_load_image (grub_efi_handle_t *part_handle) //虚拟分区引导 grub_efi_boot_services_t *b; b = grub_efi_system_table->boot_services; - if (!part_handle) + if (!part_path) return NULL; - boot_file = grub_efi_file_device_path (grub_efi_get_device_path (part_handle), - EFI_REMOVABLE_MEDIA_FILE_NAME); //文件设备路径(设备路径, 可移动媒体文件名) + boot_file = grub_efi_file_device_path (part_path, EFI_REMOVABLE_MEDIA_FILE_NAME); //文件设备路径(设备路径, 可移动媒体文件名) if (debug > 1) grub_efi_print_device_path(boot_file); //加载映像 将EFI映像加载到内存中 要读磁盘 @@ -3508,19 +3558,71 @@ vpart_load_image (grub_efi_handle_t *part_handle) //虚拟分区引导 { if (boot_file) grub_free (boot_file); - grub_printf ("Failed to load image\n"); + printf_errinfo ("Failed to load virtual partition image.\n"); return NULL; } return boot_image_handle; } -void renew_part_data (void); +void add_part_data (int drive); void -renew_part_data (void) +add_part_data (int drive) { - free_part_data (partition_info); - partition_info = 0; - partition_info_init (); + struct grub_part_data *p; //efi分区数据 + struct grub_part_data *dp; //efi分区数据 + unsigned int back_saved_drive = saved_drive; + unsigned int back_current_drive = current_drive; + unsigned int back_saved_partition = saved_partition; + unsigned int back_current_partition = current_partition; + + //查找分区数据结束 + dp = partition_info; + while (dp->next) + dp = dp->next; + + + unsigned int part = 0xFFFFFF; + unsigned long long start, len, offset; + unsigned int type, entry1, ext_offset1; + saved_drive = current_drive = drive; + saved_partition = current_partition = part; + while (( next_partition_drive = drive, + next_partition_dest = 0xFFFFFF, + next_partition_partition = &part, + next_partition_type = &type, + next_partition_start = &start, + next_partition_len = &len, + next_partition_offset = &offset, + next_partition_entry = &entry1, + next_partition_ext_offset = &ext_offset1, + next_partition_buf = mbr, + next_partition ())) + { + p = grub_malloc (sizeof (*p)); //分配内存 + if(! p) //如果分配内存失败 + return; + if (*next_partition_type == 0 || *next_partition_type == 5 || *next_partition_type == 0xf) + continue; + + //填充设备结构 + p->drive = drive; + p->partition = *next_partition_partition; + p->partition_type = *next_partition_type; + p->partition_start = *next_partition_start; + p->partition_len = *next_partition_len; + p->partition_offset = *next_partition_offset; + p->partition_entry = *next_partition_entry; + p->partition_ext_offset = *next_partition_ext_offset; + grub_memcpy (&p->partition_signature, &partition_signature, 16); + p->next = 0; + dp->next = p; + dp = p; + } + + saved_drive = back_saved_drive; + current_drive = back_current_drive; + saved_partition = back_saved_partition; + current_partition = back_current_partition; } //获得uuid; 创建设备节点; 附加设备节点; 安装多协议接口; 连接控制器; @@ -3598,14 +3700,14 @@ vdisk_install (int slot_number) //安装虚拟磁盘(映射插槽号) d->total_sectors = disk_drive_map[slot_number].sector_count; d->drive = disk_drive_map[slot_number].from_drive; d->next = 0; - if (disk_drive_map[slot_number].from_drive >= 0xa0) + if (d->drive >= 0xa0) { cdrom_orig++; if (!cd_devices) cd_devices = d; p = cd_devices; } - else if (disk_drive_map[slot_number].from_drive >= 0x80) + else if (d->drive >= 0x80) { harddrives_orig++; if (!hd_devices) @@ -3625,21 +3727,24 @@ vdisk_install (int slot_number) //安装虚拟磁盘(映射插槽号) for (; p->next; p = p->next); p->next = d; } - if (disk_drive_map[slot_number].from_drive >= 0x80 && disk_drive_map[slot_number].from_drive <= 0x8f) + if (d->drive >= 0x80 && d->drive <= 0x8f) { - renew_part_data (); + add_part_data (d->drive); } - if (disk_drive_map[slot_number].from_drive >= 0xa0) + if (d->drive >= 0x80) { - get_efi_cdrom_device_boot_path(disk_drive_map[slot_number].from_drive); - grub_sprintf (buf, "(0x%X)0x%lX+0x%lX %s", disk_drive_map[slot_number].from_drive, part_addr, part_size, - (filesystem_type == 0x100 ? "(hd)" : "(fd)")); + if (d->drive >= 0xa0) + get_efi_cdrom_device_boot_path(d->drive); + else + get_efi_hd_device_boot_path (d->drive); + + grub_sprintf (buf, "(0x%X)0x%lX+0x%lX (fd)", d->drive, part_addr, part_size); no_install_vdisk = 1; //0/1=安装虚拟磁盘/不安装虚拟磁盘 k = map_func (buf, 1); no_install_vdisk = 0; - struct grub_disk_data *d1 = get_device_by_drive (disk_drive_map[slot_number].from_drive); - vpart_install (k >> 8, d1->device_path, 0); //安装虚拟分区 + struct grub_disk_data *d1 = get_device_by_drive (d->drive); + vpart_install (k >> 8, d1->device_path, part_data); //安装虚拟分区 } status = efi_call_6 (b->install_multiple_protocol_interfaces, //安装多协议接口 @@ -3647,7 +3752,7 @@ vdisk_install (int slot_number) //安装虚拟磁盘(映射插槽号) &dp_guid, disk_drive_map[slot_number].dp, //指向协议GUID的指针,指向设备路径的指针 &blk_io_guid, &disk_drive_map[slot_number].block_io, NULL); //指向io设备接口的指针,指向block_io设备接口的指针,NULL //刚刚获得from_handle - d->handle = disk_drive_map[slot_number].from_handle; + d->device_handle = disk_drive_map[slot_number].from_handle; if (status != GRUB_EFI_SUCCESS) //安装失败 { printf_errinfo ("failed to install virtual disk\n"); //无法安装虚拟磁盘 @@ -3741,7 +3846,7 @@ vdisk_load_image (unsigned int drive) //虚拟磁盘引导 { //windows启动cdrom时,只启动第一个cdrom,因此如果有多个cdrom,必须把要启动的cdrom移动到第一位。 d = get_device_by_drive (drive); - saved_handle = d->handle; + saved_handle = d->device_handle; if (!orig_locate_handle) { @@ -3771,7 +3876,7 @@ vdisk_load_image (unsigned int drive) //虚拟磁盘引导 if(status != GRUB_EFI_SUCCESS) //如果失败 { - grub_printf ("SimpleFileSystemProtocol not found.\n"); //未找到简单文件系统协议 + printf_errinfo ("SimpleFileSystemProtocol not found.\n"); //未找到简单文件系统协议 return NULL; } for (i = 0; i < count; i++) @@ -3840,7 +3945,7 @@ vdisk_load_image (unsigned int drive) //虚拟磁盘引导 if (!boot_image_handle) { - grub_printf ("boot_image_handle not found\n"); + printf_errinfo ("Failed to load virtual disk image.\n"); return NULL; } @@ -4008,6 +4113,8 @@ grub_efidisk_init (void) //efidisk初始化 #if defined(__i386__) is64bit = check_64bit_and_PAE (); +#else + is64bit = 3; #endif if (!image) @@ -4123,7 +4230,7 @@ grub_efidisk_init (void) //efidisk初始化 //00 00 00 00 00 7f ff 04 - 00 int i; - int ret; + int ret = 0; for (i=0; i<0xff; i++) { d = get_device_by_drive (i); @@ -4134,30 +4241,32 @@ grub_efidisk_init (void) //efidisk初始化 if (ret == 0) //如果相同 break; } - boot_drive = i; - struct grub_part_data *fq; - for (fq = partition_info; fq; fq = fq->next) - { - if (fq->drive == boot_drive && fq->partition_start == part_start) - install_partition = fq->partition; - } - -//初始值: boot_drive=current_drive=0xFFFFFFFF saved_drive=0 -//初始值: install_partition=0x00FFFFFF saved_partition=current_partition=0 - saved_drive = boot_drive; - current_drive = boot_drive; - saved_partition = install_partition; - current_partition = install_partition; - debug = 1; + if (i != 0xff) + { + boot_drive = i; + struct grub_part_data *fq; + for (fq = partition_info; fq; fq = fq->next) + { + if (fq->drive == boot_drive && fq->partition_start == part_start) + install_partition = fq->partition; + } + //初始值: boot_drive=current_drive=0xFFFFFFFF saved_drive=0 + //初始值: install_partition=0x00FFFFFF saved_partition=current_partition=0 + saved_drive = boot_drive; + current_drive = boot_drive; + saved_partition = install_partition; + current_partition = install_partition; + ret = find_specified_file (current_drive, current_partition, "/efi/grub/menu.lst"); + } + //初始化变量空间 run_line((char *)"set ?_BOOT=%@root%",1); QUOTE_CHAR = '\"'; run_line((char *)"errorcheck off",1); -// run_line((char *)"configfile /menu.lst",1); -// run_line((char *)"configfile /boot/grub/menu.lst",1); -// run_line((char *)"configfile /grub/menu.lst",1); + if (!ret || i == 0xff) + run_line((char *)"find --set-root /efi/grub/menu.lst",1); run_line((char *)"configfile /efi/grub/menu.lst",1); run_line((char *)"errorcheck on",1); diff --git a/stage2/gunzip.c b/stage2/gunzip.c index 7016726a..ebe0e713 100644 --- a/stage2/gunzip.c +++ b/stage2/gunzip.c @@ -366,6 +366,7 @@ void gunzip_close (void) { grub_free(linalloc_buf); + linalloc_buf = 0; } diff --git a/stage2/pc_slice.h b/stage2/pc_slice.h index ecc652b0..3e215dee 100644 --- a/stage2/pc_slice.h +++ b/stage2/pc_slice.h @@ -32,6 +32,8 @@ #define PC_SLICE_OFFSET 446 #define PC_SLICE_MAX 4 +#define PC_DISK_SIG_OFFSET 0x1b8 + /* * Defines to guarantee structural alignment. @@ -102,6 +104,9 @@ ( *( (unsigned long long *) (((grub_size_t) mbr_ptr) + PC_SLICE_OFFSET + 8 \ + (part << 4)) ) ) ) ) +//获取磁盘签名 +#define PC_DISK_SIG(mbr_ptr) \ + ( *( (unsigned int *) (((grub_size_t) mbr_ptr) + PC_DISK_SIG_OFFSET) ) ) /* * PC flag types are defined here. diff --git a/stage2/shared.h b/stage2/shared.h index 38e51b8b..4c018274 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -97,7 +97,7 @@ #define DRIVE_MAP_SLOT_SIZE 0x70 /* The fragment of the drive map. */ -#define DRIVE_MAP_FRAGMENT 32 +#define DRIVE_MAP_FRAGMENT 0x27 #define FRAGMENT_MAP_SLOT_SIZE 0x280 @@ -2243,6 +2243,7 @@ extern int big_to_little (char *filename, unsigned int n); grub_efi_ prepended. */ /* Constants. 常量 */ +//事件的类型 #define GRUB_EFI_EVT_TIMER 0x80000000 //计时器 #define GRUB_EFI_EVT_RUNTIME 0x40000000 //运行 #define GRUB_EFI_EVT_RUNTIME_CONTEXT 0x20000000 //运行环境 @@ -2250,7 +2251,7 @@ extern int big_to_little (char *filename, unsigned int n); #define GRUB_EFI_EVT_NOTIFY_SIGNAL 0x00000200 //通知信号 #define GRUB_EFI_EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201 //信号出口启动服务 #define GRUB_EFI_EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 //信号虚拟地址变更 - +//事件的优先级 #define GRUB_EFI_TPL_APPLICATION 4 //应用 #define GRUB_EFI_TPL_CALLBACK 8 //回调 #define GRUB_EFI_TPL_NOTIFY 16 //通知 @@ -2803,7 +2804,7 @@ typedef enum grub_efi_reset_type grub_efi_reset_type_t; #define GRUB_EFI_LOAD_ERROR GRUB_EFI_ERROR_CODE (1) //加载错误 #define GRUB_EFI_INVALID_PARAMETER GRUB_EFI_ERROR_CODE (2) //无效参数 #define GRUB_EFI_UNSUPPORTED GRUB_EFI_ERROR_CODE (3) //不支持 -#define GRUB_EFI_BAD_BUFFER_SIZE GRUB_EFI_ERROR_CODE (4) //缓冲区大小 +#define GRUB_EFI_BAD_BUFFER_SIZE GRUB_EFI_ERROR_CODE (4) //参数不是设备固有块大小的倍数 #define GRUB_EFI_BUFFER_TOO_SMALL GRUB_EFI_ERROR_CODE (5) //缓存太小 #define GRUB_EFI_NOT_READY GRUB_EFI_ERROR_CODE (6) //还没准备好 #define GRUB_EFI_DEVICE_ERROR GRUB_EFI_ERROR_CODE (7) //设备错误 @@ -3511,23 +3512,25 @@ struct grub_efi_boot_services //引导服务 grub_efi_status_t EFIAPI (*free_pool) (void *buffer); //释放池 + //创建事件 grub_efi_status_t EFIAPI - (*create_event) (grub_efi_uint32_t type, - grub_efi_tpl_t notify_tpl, + (*create_event) (grub_efi_uint32_t type, //事件的类型 + grub_efi_tpl_t notify_tpl, //事件的优先级 void (*notify_function) (grub_efi_event_t event, - void *context), - void *notify_context, - grub_efi_event_t *event); //创建事件 + void *context), //事件处理函数 + void *notify_context, //传递给事件处理函数的参数 + grub_efi_event_t *event); //创建的事件 grub_efi_status_t EFIAPI (*set_timer) (grub_efi_event_t event, grub_efi_timer_delay_t type, grub_efi_uint64_t trigger_time); //设置时间 - + + //等待事件 grub_efi_status_t EFIAPI - (*wait_for_event) (grub_efi_uintn_t num_events, - grub_efi_event_t *event, - grub_efi_uintn_t *index); //等待事件 + (*wait_for_event) (grub_efi_uintn_t num_events, //第二个参数Event中的事件数量 + grub_efi_event_t *event, //所要等待的事件数组 + grub_efi_uintn_t *index); //指向满足等待条件的事件索引的指针 grub_efi_status_t EFIAPI (*signal_event) (grub_efi_event_t event); //信号事件 @@ -5254,6 +5257,8 @@ extern unsigned long long *next_partition_offset; extern unsigned int *next_partition_entry; extern unsigned int *next_partition_ext_offset; extern char *next_partition_buf; +extern unsigned char partition_signature[16]; //分区签名 +extern unsigned char partition_activity_flag; //分区活动标志 extern unsigned char *UNIFONT_START; extern char *PAGING_TABLES_BUF; extern unsigned char *PRINTF_BUFFER; @@ -5460,7 +5465,7 @@ grub_decompress_lzss (grub_uint8_t *dst, grub_uint8_t *dstend, struct grub_disk_data //efi磁盘数据 (软盘,硬盘,光盘) grub2定义 { - grub_efi_handle_t handle; //句柄 11cba410 hndl + grub_efi_handle_t device_handle; //句柄 11cba410 hndl grub_efi_device_path_t *device_path; //设备路径 11cba890 类型,子类型,长度 grub_efi_device_path_t *last_device_path; //最后设备路径 11cba8a2 类型,子类型,长度 grub_efi_block_io_t *block_io; //块输入输出 1280d318 修订,媒体,重置,读块,写块,清除块 @@ -5473,16 +5478,20 @@ struct grub_disk_data //efi磁盘数据 (软盘,硬盘,光盘) grub2定义 struct grub_part_data //efi分区数据 (硬盘) grub定义 { - unsigned char drive; //驱动器 - unsigned char partition_entry; //分区入口 - unsigned char partition_type; //分区类型 - unsigned char filesystem_type; //文件系统类型 - unsigned int partition; //当前分区 - unsigned int partition_ext_offset; //扩展分区偏移 - unsigned long long partition_start; //分区起始扇区 - unsigned long long partition_len; //分区扇区尺寸 - unsigned long long partition_offset; //分区偏移 - struct grub_part_data *next; //下一个 + grub_efi_handle_t part_handle; //句柄 + grub_efi_device_path_t *part_path; //分区路径 + grub_efi_device_path_t *last_part_path; //最后分区路径 + struct grub_part_data *next; //下一个 + unsigned char drive; //驱动器 + unsigned char partition_type; //MBR分区ID + unsigned char partition_activity_flag; //分区活动标志 + unsigned char partition_entry; //分区入口 + unsigned int partition_ext_offset; //扩展分区偏移 + unsigned int partition; //当前分区 + unsigned long long partition_offset; //分区偏移 + unsigned long long partition_start; //分区起始扇区 + unsigned long long partition_len; //分区扇区尺寸 + unsigned char partition_signature[16]; //分区签名 } __attribute__ ((packed)); //0x28 extern struct grub_part_data *get_partition_info (int drive, int partition); @@ -5526,7 +5535,8 @@ struct fragment //extern struct drive_map_slot vpart_drive_map[DRIVE_MAP_SIZE + 1]; extern struct drive_map_slot disk_drive_map[DRIVE_MAP_SIZE + 1]; extern struct fragment_map_slot disk_fragment_map; -extern char disk_buffer[0x1000]; +//extern char disk_buffer[0x1000]; +extern char *disk_buffer; extern int drive_map_slot_empty (struct drive_map_slot item); extern struct fragment_map_slot *fragment_map_slot_find(struct fragment_map_slot *q, unsigned int from); @@ -5656,16 +5666,16 @@ struct grub_packed_guid typedef struct grub_packed_guid grub_packed_guid_t; extern grub_packed_guid_t VDISK_GUID; -extern grub_efi_uint64_t signature; extern grub_efi_uint64_t boot_entry; extern grub_efi_uint64_t part_addr; extern grub_efi_uint64_t part_size; +extern struct grub_part_data *part_data; void file_read (grub_efi_boolean_t disk, void *file, void *buf, grub_efi_uintn_t len, grub_efi_uint64_t offset); grub_efi_uint64_t get_size (grub_efi_boolean_t disk, void *file); /* vboot */ -extern grub_efi_handle_t vpart_load_image (grub_efi_handle_t *part_handle); +extern grub_efi_handle_t vpart_load_image (grub_efi_device_path_t *part_path); extern grub_efi_handle_t vdisk_load_image (unsigned int drive); /* vdisk */ extern grub_efi_status_t vdisk_install (int slot_number); @@ -5860,6 +5870,11 @@ extern int gopprobe (char *arg, int flags); ////////////////////////////////////////////////////////////////////////////////// /* Based on UEFI specification. 基于UEFI规范 */ +/* +GOP (图形输出协议) +GOP (Graphic Output Protocol),是用来将图形驱动程序延伸至UEFI固件的接口,借以取代传统VBIOS(视讯BIOS)在开机资源要求等初始化行为。 +GOP: 无 64 KB 的限制。32 位元保护模式。不需要 CSM。速度最佳化 (快速开机支持)。 +*/ #define GRUB_EFI_GOP_GUID \ { 0x9042a9de, 0x23dc, 0x4a38, { 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a }} @@ -6825,7 +6840,9 @@ extern grub_efi_physical_address_t grub4dos_self_address; extern grub_uint64_t grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r); extern grub_uint64_t EXPORT_FUNC (__umoddi3) (grub_uint64_t a, grub_uint64_t b); extern grub_uint64_t EXPORT_FUNC (__udivdi3) (grub_uint64_t a, grub_uint64_t b); - +extern void start_event (void); +extern void close_event (void); +extern int find_specified_file (int drive, int partition, char* file); //====================================================================================================================== #endif /* ! ASM_FILE */ diff --git a/stage2/stage2.c b/stage2/stage2.c index c6c11009..8f452d5e 100644 --- a/stage2/stage2.c +++ b/stage2/stage2.c @@ -606,6 +606,7 @@ run_script (char *script, char *heap) grub_sprintf (cmd_add, "(md)%d+%d", (grub_size_t)p >> 9, ((cur_entry - script + 10 + 511) & ~511) >> 9); command_func (cmd_add, BUILTIN_SCRIPT); grub_free(menu_bat); + menu_bat = 0; if (errnum >= 1000) { errnum=ERR_NONE; @@ -1999,7 +2000,7 @@ cmain (void) pxe_restart_config = 0; #ifdef SUPPORT_GFX - *graphics_file = 0; +// *graphics_file = 0; #endif //DEBUG_SLEEP /* Only uncomment if you want to pause before processing every menu.lst line */ /* Copy the first string in CUR_ENTRY to HEAP. */