#!/usr/bin/env python3 # Собирает загрузочный ESP-образ (FAT16) c /EFI/BOOT/BOOTX64.EFI. # Без mtools/mkfs — вручную по спецификации FAT, плюс самопроверка (обход обратно). import struct, sys, os, math EFI = sys.argv[1] if len(sys.argv)>1 else "/data/work/chat_-1002129270612/plan9/build/efi/bootx64.efi" OUT = sys.argv[2] if len(sys.argv)>2 else "/data/work/chat_-1002129270612/plan9/build/efi/esp.img" data = open(EFI,"rb").read() BPS=512; SPC=1; RSVD=1; NFAT=2; ROOTENT=512; TOT=8192 rootsecs=(ROOTENT*32+BPS-1)//BPS tmp1=TOT-(RSVD+rootsecs); tmp2=256*SPC+NFAT FATSZ=(tmp1+tmp2-1)//tmp2 first_data=RSVD+NFAT*FATSZ+rootsecs nclus=(TOT-first_data)//SPC assert nclus>4085, f"стало бы FAT12 ({nclus} кластеров)" img=bytearray(TOT*BPS) # --- boot sector / BPB --- bs=img bs[0:3]=b'\xEB\x3C\x90'; bs[3:11]=b'MSWIN4.1' struct.pack_into(' cl2) root_off=(RSVD+NFAT*FATSZ)*BPS img[root_off:root_off+32]=dirent("EFI","",0x10,efi_cl,0) # EFI dir (cl2): '.', '..', BOOT(dir->cl3) o=clus_off(efi_cl) img[o:o+32]=dirent(".","",0x10,efi_cl,0) img[o+32:o+64]=dirent("..","",0x10,0,0) img[o+64:o+96]=dirent("BOOT","",0x10,boot_cl,0) # BOOT dir (cl3): '.', '..', BOOTX64.EFI(file->cl4) o=clus_off(boot_cl) img[o:o+32]=dirent(".","",0x10,boot_cl,0) img[o+32:o+64]=dirent("..","",0x10,efi_cl,0) img[o+64:o+96]=dirent("BOOTX64","EFI",0x20,file_cl,len(data)) # данные файла for i,c in enumerate(file_clusters): chunk=data[i*BPS*SPC:(i+1)*BPS*SPC] off=clus_off(c); img[off:off+len(chunk)]=chunk open(OUT,"wb").write(img) # --- САМОПРОВЕРКА: обойти FAT и достать /EFI/BOOT/BOOTX64.EFI --- im=open(OUT,"rb").read() def rd(a,n): return im[a:a+n] def fat(c): return struct.unpack_from('