diff --git a/ChangeLog_UEFI.txt b/ChangeLog_UEFI.txt index 73a5f5f..7ca0016 100644 --- a/ChangeLog_UEFI.txt +++ b/ChangeLog_UEFI.txt @@ -1,4 +1,8 @@ 更新说明: +2023-11-27 (yaya) + 修正碎片插槽计算。 + 改进pxe。 + 2023-10-14 (yaya) 修正增加变量menu_tab_ext引入的问题。 修正font函数。 diff --git a/stage2/asm.S b/stage2/asm.S index c8c20de..3650827 100644 --- a/stage2/asm.S +++ b/stage2/asm.S @@ -382,6 +382,8 @@ VARIABLE(menu_mem) //0x8388 菜单 char * . = EXT_C(main) + 0x190 //0x8390 +VARIABLE(efi_pxe_buf) //char * 2023-11-24 + .long 0, 0 .long 0 .long 0 .long 0 @@ -618,7 +620,7 @@ VARIABLE(system_functions) //IMG(0x8300) .extent ABS(EXT_C(grub_read)) //27 .extent ABS(EXT_C(grub_close)) //28 .extent ABS(EXT_C(get_device_by_drive)) //29 grub_disk_data * - .extent 0 //30 reserved + .extent ABS(EXT_C(tftp_write)) //30 int VARIABLE(disk_read_hook) .extent 0 //31 .extent ABS(EXT_C(devread)) //32 diff --git a/stage2/builtins.c b/stage2/builtins.c index 8ac9afd..3ae754f 100644 --- a/stage2/builtins.c +++ b/stage2/builtins.c @@ -842,7 +842,8 @@ map_to_svbus (grub_efi_physical_address_t address) #endif //复制碎片插槽 - grub_memmove ((char *)((char *)(grub_size_t)address + 0x148), (char *)&disk_fragment_map, FRAGMENT_MAP_SLOT_SIZE); +// grub_memmove ((char *)((char *)(grub_size_t)address + 0x148), (char *)&disk_fragment_map, FRAGMENT_MAP_SLOT_SIZE); + grub_memmove ((char *)((char *)(grub_size_t)address + 0x148), (char *)disk_fragment_map, FRAGMENT_MAP_SLOT_SIZE); } //使用于get_efi_device_boot_path,find_specified_file,chainloader_func,command_func,uuid_func @@ -1484,6 +1485,13 @@ chainloader_func (char *arg, int flags) } printf_debug("current_drive=%x, current_partition=%x\n",current_drive,current_partition); + if (current_drive == 0x21) //2023-11-24 + { + dp = pd_dp; //网起设备路径 + temp = pd_handle; //网起设备句柄 + } + else + { // if (current_drive >= 0xa0) //使用光盘启动镜像的句柄和路径 2023-10-14 // current_partition = 0xffff; //如果当前设备是(cd-1),使用光盘的路径;如果当前设备是(cd-1,0),使用光盘启动镜像的路径。 2023-10-16 @@ -1503,6 +1511,7 @@ chainloader_func (char *arg, int flags) dp = grub_efi_get_device_path (part_data->part_handle); temp = part_data->part_handle; } + } if (debug > 1) grub_efi_print_device_path(dp); @@ -7246,9 +7255,11 @@ unload_fragment_slot (unsigned int from) //卸载碎片插槽 void *start; int len; - q = (struct fragment_map_slot *)&disk_fragment_map; //q=碎片映射插槽起始位置 *q=插槽尺寸 b6e0 +// q = (struct fragment_map_slot *)&disk_fragment_map; //q=碎片映射插槽起始位置 *q=插槽尺寸 b6e0 + q = (struct fragment_map_slot *)disk_fragment_map; //q=碎片映射插槽起始位置 *q=插槽尺寸 b6e0 // filename = (char *)q + FRAGMENT_MAP_SLOT_SIZE; //碎片映射插槽终止位置 - grub_size_t size = (grub_size_t)&disk_fragment_map + FRAGMENT_MAP_SLOT_SIZE; +// grub_size_t size = (grub_size_t)&disk_fragment_map + FRAGMENT_MAP_SLOT_SIZE; + grub_size_t size = (grub_size_t)disk_fragment_map + FRAGMENT_MAP_SLOT_SIZE; q = fragment_map_slot_find(q, from); //q=from驱动器在碎片映射插槽起始位置 if (q) //0/1=没有找到驱动器/找到驱动器位置 { @@ -8221,9 +8232,11 @@ struct drive_map_slot df = get_device_by_drive (from,1); if (df && df->fragment == 1) //有碎片 { - q = (struct fragment_map_slot *)&disk_fragment_map; //碎片插槽起始 +// q = (struct fragment_map_slot *)&disk_fragment_map; //碎片插槽起始 + q = (struct fragment_map_slot *)disk_fragment_map; //碎片插槽起始 // filename = (char *)q + FRAGMENT_MAP_SLOT_SIZE; //碎片插槽结束 - grub_size_t size = (grub_size_t)&disk_fragment_map + FRAGMENT_MAP_SLOT_SIZE; +// grub_size_t size = (grub_size_t)&disk_fragment_map + FRAGMENT_MAP_SLOT_SIZE; + grub_size_t size = (grub_size_t)disk_fragment_map + FRAGMENT_MAP_SLOT_SIZE; q = fragment_map_slot_find(q, from); //从碎片插槽查找from驱动器 if (q) //q=0/非0=没有找到/from驱动器在碎片插槽位置 { @@ -8493,14 +8506,15 @@ struct drive_map_slot if (to == ram_drive) //如果to=rd start_byte += rd_base; //起始字节+rd基址 /////////////////////////////////////////////////////////////////////////////////////////////////////以下插入分配内存 - - if (to == 0x21) //网络驱动器 +#if 0 //2023-11-24 + if (to == 0x21) //网络驱动器 { // disk_drive_map[i].start_sector = ((unsigned long long)(grub_size_t)(char*)efi_pxe_buf | 0x200) & 0xfffffffffffffe00; //此处是内存起始字节!!! start_sector = ((unsigned long long)(grub_size_t)(char*)efi_pxe_buf | 0x200) & 0xfffffffffffffe00; //此处是内存起始字节!!! efi_pxe_buf = 0; } else //其他 +#endif { if (prefer_top) //分配4GB以上内存 { @@ -8690,7 +8704,8 @@ struct drive_map_slot grub_memmove64 ((unsigned long long)(grub_size_t)p1, (unsigned long long)(grub_size_t)map_start_sector, DRIVE_MAP_FRAGMENT * 8); grub_memmove64 ((unsigned long long)(grub_size_t)p2, (unsigned long long)(grub_size_t)map_start_sector, DRIVE_MAP_FRAGMENT * 8); //查找父插槽To_ - q = (struct fragment_map_slot *)&disk_fragment_map; +// q = (struct fragment_map_slot *)&disk_fragment_map; + q = (struct fragment_map_slot *)disk_fragment_map; q = fragment_map_slot_find(q, primeval_to); struct fragment *to_ = (struct fragment *)&q->fragment_data; @@ -8755,7 +8770,8 @@ struct drive_map_slot goto no_fragment; } //查找空槽 - q = (struct fragment_map_slot *)&disk_fragment_map; +// q = (struct fragment_map_slot *)&disk_fragment_map; + q = (struct fragment_map_slot *)disk_fragment_map; filename = (char *)q; q = fragment_map_slot_empty(q); //出界检查 diff --git a/stage2/common.c b/stage2/common.c index 0dab600..6412343 100644 --- a/stage2/common.c +++ b/stage2/common.c @@ -2248,7 +2248,7 @@ char *CMD_RUN_ON_EXIT; char *SCRATCHADDR; char *mbr; char *disk_buffer; -struct fragment_map_slot *disk_fragment_map; +//struct fragment_map_slot *disk_fragment_map; //char * void grub_console_init (void); diff --git a/stage2/disk_io.c b/stage2/disk_io.c index 629fd70..f8ec800 100644 --- a/stage2/disk_io.c +++ b/stage2/disk_io.c @@ -3052,7 +3052,8 @@ grub_efidisk_readwrite (int drive, grub_disk_addr_t sector, if (df->fragment) { //从碎片插槽查找Form驱动器 - q = (struct fragment_map_slot *)&disk_fragment_map; +// q = (struct fragment_map_slot *)&disk_fragment_map; + q = (struct fragment_map_slot *)disk_fragment_map; q = fragment_map_slot_find (q, from_drive); //确定Form扇区起始在哪个碎片 data = (struct fragment *)&q->fragment_data; @@ -5028,7 +5029,8 @@ EFI_STATUS grub_hook_1st_cdrom_stop(VOID) //钩第一光盘结束 } #endif - +grub_efi_handle_t pd_handle; +grub_efi_device_path_t *pd_dp; //void GRUB_MOD_INIT_efinet(void); //int force_pxe_as_boot_device = 0; void grub_efidisk_init (void); @@ -5116,6 +5118,8 @@ grub_efidisk_init (void) //efidisk初始化 run_line((char *)"set ?_BOOT=%@root%",1); // QUOTE_CHAR = '\"'; *saved_dir = 0; + pd_handle = image->device_handle; //2023-11-24 + pd_dp = dp; cmain (); return; } diff --git a/stage2/fsys_pxe.c b/stage2/fsys_pxe.c index a70bf37..3d90d87 100644 --- a/stage2/fsys_pxe.c +++ b/stage2/fsys_pxe.c @@ -101,7 +101,6 @@ static unsigned int pxe_saved_pos, pxe_cur_ofs, pxe_read_ofs; //保存的指针, extern PXENV_TFTP_OPEN_t pxe_tftp_open; /* now it is defined in asm.S 现在它在asm.S中定义*/ //TFTP打开 static char filename[128]; static char *pxe_tftp_name = filename; -char *efi_pxe_buf = 0; //extern unsigned int ROM_int15; //extern unsigned int ROM_int13; @@ -109,11 +108,13 @@ char *efi_pxe_buf = 0; extern struct drive_map_slot bios_drive_map[DRIVE_MAP_SIZE + 1]; static int pxe_open (char* name); +int pxe_dir (char *dirname); grub_u32_t pxe_read_blk (grub_u32_t buf, grub_u32_t num); static int tftp_open(const char *dirname); static grub_u32_t tftp_get_size(void); static grub_u32_t tftp_read_blk (grub_u32_t buf, grub_u32_t num); +int tftp_write (const char *name); static void tftp_close (void); static void tftp_unload(void); @@ -217,7 +218,8 @@ BOOTPLAYER *discover_reply = 0; //引导播放器 static void set_basedir(char *config); static void set_basedir(char *config) //设置基本目录 { - unsigned int n; +// unsigned int n; + int n; //2023-11-24 grub_u8_t path_sep = (cur_pxe_type == PXE_FILE_TYPE_TFTP && server_is_dos) ? '\\' : '/'; //路径分隔 n = grub_strlen (config); //字符串尺寸 @@ -735,18 +737,17 @@ pxe_read (unsigned long long buf, unsigned long long len, unsigned int write) // FILEMAX. return 1 if succeed, 0 if fail. */ //获取尺寸并将其保存在FILEMAX中。 如果成功则返回1,如果失败则返回0 struct pxe_dir_info //目录信息 { - char path[512]; //路径 - char *dir[512]; //目录 - char data[]; //数据 -} *P_DIR_INFO = NULL; + char path[512]; //路径 尺寸0x200 e3d64c0 /boot/dir.txt + char *dir[512]; //目录 尺寸0x1000 e3d66c0 e3d76c0 e3d76c5 e3d76d2 ... + char data[]; //数据 尺寸0x2e00 e3d76c0 bcd\0\a bcdedit.exe\0\a boot.sdi\0\a bootmgr.exe\0\a wimboot\0\a +} *P_DIR_INFO = NULL;//尺寸0x4000 -int pxe_dir (char *dirname); int pxe_dir (char *dirname) //pxe查目录 { int ret; char ch; ret = 1; - ch = nul_terminate (dirname); //用"0"替换"\0" + ch = nul_terminate (dirname); //以00替换止字符串的空格,回车,换行,水平制表符 if (print_possibilities) //如果存在打印可能性 { @@ -771,16 +772,17 @@ int pxe_dir (char *dirname) //pxe查目录 { int i; char *p = P_DIR_INFO->data; + memset(P_DIR_INFO,0,16384); if (substring(dir_tmp,P_DIR_INFO->path,1) != 0) //判断子字符串 { - memset(P_DIR_INFO,0,16384); grub_strcpy(P_DIR_INFO->path,dir_tmp); if (pxe_open(dir_tmp)) { - if (pxe_read((unsigned long long)(grub_size_t)P_DIR_INFO->data,13312,GRUB_READ)) +// if (pxe_read((unsigned long long)(grub_size_t)P_DIR_INFO->data,13312,GRUB_READ)) //13312计算错误 + if (pxe_read((unsigned long long)(grub_size_t)P_DIR_INFO->data,filemax,GRUB_READ)) //替换filemax,是因为读长了会把后面无用的字符串读入 2023-11-24 { P_DIR_INFO->dir[0] = P_DIR_INFO->data; - for (i = 1;i < 512 && (p = skip_to(0x100,p));++i) + for (i = 1;i < 512 && (p = skip_to(0x100,p));++i) //遇到首个"回车,换行",使用'\0'替换.然后跳过之后的"回车,换行,空格,水平制表符", { P_DIR_INFO->dir[i] = p; } @@ -838,7 +840,7 @@ static int tftp_open(const char *name) //tftp打开 if (!tftp_get_size()) return 0; - tftp_close (); +// tftp_close (); //2023-11-24 status = efi_call_3 (b->allocate_pool, GRUB_EFI_BOOT_SERVICES_DATA, //启动服务数据 4 filemax + 0x200, (void**)&efi_pxe_buf); //(分配池,存储器类型->装载数据,分配字节,返回分配地址} if (status != GRUB_EFI_SUCCESS) //失败 @@ -846,11 +848,12 @@ static int tftp_open(const char *name) //tftp打开 printf_errinfo ("Couldn't allocate pool."); return 0; } + memset(efi_pxe_buf,0,filemax); //2023-11-24 status = efi_call_10 (pxe_entry->mtftp, //tftp功能 pxe_entry, //pxe结构 GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE, //TFTP读文件 - efi_pxe_buf, //缓存 + (char *)efi_pxe_buf, //缓存 0, (grub_efi_uint64_t *)(grub_size_t)&filemax,//缓存尺寸 NULL, //块尺寸 @@ -896,13 +899,35 @@ static grub_u32_t tftp_get_size(void) //TFTP获得文件尺寸 return filemax; } -static grub_u32_t tftp_read_blk (grub_u32_t buf, grub_u32_t num); static grub_u32_t tftp_read_blk (grub_u32_t buf, grub_u32_t num) { return 0; } -static void tftp_close (void); +int tftp_write (const char *name) //tftp写 2023-11-24 +{ + grub_efi_status_t status; + + status = efi_call_10 (pxe_entry->mtftp, //tftp功能 + pxe_entry, //pxe结构 + GRUB_EFI_PXE_BASE_CODE_TFTP_WRITE_FILE, //TFTP写文件 + (char *)efi_pxe_buf, //缓存 + 1, //可以覆盖服务器上的文件 + (grub_efi_uint64_t *)(grub_size_t)&filemax,//缓存尺寸 + NULL, //块尺寸 + (IP4 *)(grub_size_t)&pxe_sip, //服务器IP + (char *)name, //文件名 + NULL, + 0); + if (status != GRUB_EFI_SUCCESS) //失败 + { + printf_errinfo ("Couldn't open file."); + return 0; + } + + return 1; +} + static void tftp_close (void) //tftp关闭 { grub_efi_boot_services_t *b; //引导服务 @@ -913,7 +938,6 @@ static void tftp_close (void) //tftp关闭 efi_pxe_buf = 0; } -static void tftp_unload(void); static void tftp_unload(void) //tftp卸载 { if (! pxe_entry) diff --git a/stage2/shared.h b/stage2/shared.h index 1503f79..d235883 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -923,7 +923,7 @@ struct linux_kernel_header unsigned int kernel_alignment; unsigned char relocatable; unsigned char min_alignment; -#define LINUX_XLF_KERNEL_64 (1<<0) //1 64位内 +#define LINUX_XLF_KERNEL_64 (1<<0) //1 64位内内核 #define LINUX_XLF_CAN_BE_LOADED_ABOVE_4G (1<<1) //2 可加载4G以上 #define LINUX_XLF_EFI_HANDOVER_32 (1<<2) //4 支持 EFI32 Handover #define LINUX_XLF_EFI_HANDOVER_64 (1<<3) //8 支持 EFI64 Handover @@ -2243,7 +2243,7 @@ extern int is64bit; extern int errorcheck; extern unsigned int pxe_restart_config; -extern char *efi_pxe_buf; +extern grub_size_t *efi_pxe_buf; extern unsigned int saved_pxe_ip; extern unsigned char saved_pxe_mac[6]; @@ -4229,14 +4229,16 @@ typedef struct grub_efi_pxe grub_efi_pxe_base_code_tftp_opcode_t operation, //运作方式 要执行的操作类型。 char *buffer_ptr, //指向数据缓冲区的指针。 如果dont_use_buffer为TRUE,则忽略读取文件。 grub_efi_boolean_t overwrite, //覆盖,仅用于写文件操作。 如果可以覆盖远程服务器上的文件,则为TRUE。 - grub_efi_uint64_t *buffer_size, //缓冲区尺寸 对于获得文件尺寸操作,*buffer_size返回所请求文件的尺寸。对于读文件和写文件操作, + grub_efi_uint64_t *buffer_size, //缓冲区尺寸 对于获取文件尺寸操作,*buffer_size返回所请求文件的尺寸。对于读文件和写文件操作, //此参数设置为指定的缓冲区尺寸。 对于读取文件操作,如果返回EFI_BUFFER_TOO_SMALL,则*buffer_size返回所请求文件的尺寸。 grub_efi_uintn_t *block_size, //块尺寸 在TFTP传输期间要使用的请求块尺寸。 该字段必须至少为512。 //如果此字段为NULL,则将使用实现支持的最大块大小。 - grub_u32_t *server_ip, //TFTP/MTFTP服务器IP地址 + grub_u32_t *server_ip, //TFTP/MTFTP服务器IP地址 char *filename, //文件名 以Null结尾的ASCII字符串,用于指定目录名称或文件名。 MTFTP读取目录会忽略此内容。 grub_efi_pxe_base_code_mtftp_info_t *info, //指向MTFTP信息的指针。 启动或加入多播TFTP会话需要此信息。 grub_efi_boolean_t dont_use_buffer); //对于正常的TFTP和MTFTP读取文件操作,设置为FALSE。 +//TFTP读取目录操作返回的数据格式是一个以null结尾的文件名,后跟一个以null结尾的信息字符串,格式为“尺寸 年-月-日 时:分:秒” +//(即%d%d-%d-%d:%d:%f-注意秒字段可以是十进制数字),其中日期和时间为UTC。 void (*udpwrite) (void); //udp写 将UDP数据包写入网络接口。 void (*udpread) (void); //udp读 从网络接口读取UDP数据包。 void (*setipfilter) (void); //设置过滤器 更新网络设备的IP接收筛选器。 @@ -4249,7 +4251,7 @@ typedef struct grub_efi_pxe struct grub_efi_pxe_mode *mode; //模式 指向此设备的EFI_PXE_BASE_CODE_MODE数据的指针。 } grub_efi_pxe_t; - +extern int tftp_write (const char *name); #define GRUB_EFI_BLACK 0x00 //前景黑 #define GRUB_EFI_BLUE 0x01 //前景蓝 @@ -5763,6 +5765,8 @@ extern struct grub_part_data *partition_info; extern struct grub_disk_data *previous_struct; extern struct grub_part_data *get_boot_partition (int drive); extern void renew_part_data (void); +extern grub_efi_handle_t pd_handle; +extern grub_efi_device_path_t *pd_dp; struct drive_map_slot {