/* return the size or -1 if error */intget_image_size(constchar*filename){intfd,size;fd=open(filename,O_RDONLY|O_BINARY);if(fd<0)return-1;size=lseek(fd,0,SEEK_END);close(fd);returnsize;}/* return the size or -1 if error */
/* return the amount read, just like fread. 0 may mean error or eof */intfread_targphys(target_phys_addr_tdst_addr,size_tnbytes,FILE*f){uint8_tbuf[4096];target_phys_addr_tdst_begin=dst_addr;size_twant,did;while(nbytes){want=nbytes>sizeof(buf)?sizeof(buf):nbytes;did=fread(buf,1,want,f);if(did!=want)break;cpu_physical_memory_write_rom(dst_addr,buf,did);dst_addr+=did;nbytes-=did;}returndst_addr-dst_begin;}/* returns 0 on error, 1 if ok */intfread_targphys_ok(target_phys_addr_tdst_addr,size_tnbytes,FILE*f){returnfread_targphys(dst_addr,nbytes,f)==nbytes;}/* read()-like version */intread_targphys(intfd,target_phys_addr_tdst_addr,size_tnbytes){uint8_tbuf[4096];target_phys_addr_tdst_begin=dst_addr;size_twant,did;while(nbytes){want=nbytes>sizeof(buf)?sizeof(buf):nbytes;did=read(fd,buf,want);if(did!=want)break;cpu_physical_memory_write_rom(dst_addr,buf,did);dst_addr+=did;nbytes-=did;}returndst_addr-dst_begin;}/* return the size or -1 if error */intload_image_targphys(constchar*filename,target_phys_addr_taddr,intmax_sz){FILE*f;size_tgot;f=fopen(filename,"rb");if(!f)return-1;got=fread_targphys(addr,max_sz,f);if(ferror(f)){fclose(f);return-1;}fclose(f);returngot;}voidpstrcpy_targphys(target_phys_addr_tdest,intbuf_size,constchar*source){staticconstuint8_tnul_byte=0;constchar*nulp;if(buf_size<=0)return;nulp=memchr(source,0,buf_size);if(nulp){cpu_physical_memory_write_rom(dest,(uint8_t*)source,(nulp-source)+1);}else{cpu_physical_memory_write_rom(dest,(uint8_t*)source,buf_size-1);cpu_physical_memory_write_rom(dest,&nul_byte,1);}}
/* A.OUT loader */structexec{uint32_ta_info;/* Use macros N_MAGIC, etc for access */uint32_ta_text;/* length of text, in bytes */uint32_ta_data;/* length of data, in bytes */uint32_ta_bss;/* length of uninitialized data area, in bytes */uint32_ta_syms;/* length of symbol table data in file, in bytes */uint32_ta_entry;/* start address */uint32_ta_trsize;/* length of relocation info for text, in bytes */uint32_ta_drsize;/* length of relocation info for data, in bytes */};#ifdefBSWAP_NEEDEDstaticvoidbswap_ahdr(structexec*e){bswap32s(&e->a_info);bswap32s(&e->a_text);bswap32s(&e->a_data);bswap32s(&e->a_bss);bswap32s(&e->a_syms);bswap32s(&e->a_entry);bswap32s(&e->a_trsize);bswap32s(&e->a_drsize);}#else#definebswap_ahdr(x)do{}while(0)#endif#defineN_MAGIC(exec)((exec).a_info&0xffff)#defineOMAGIC0407#defineNMAGIC0410#defineZMAGIC0413#defineQMAGIC0314#define_N_HDROFF(x)(1024-sizeof(structexec))#defineN_TXTOFF(x)\(N_MAGIC(x)==ZMAGIC?_N_HDROFF((x))+sizeof(structexec):\(N_MAGIC(x)==QMAGIC?0:sizeof(structexec)))#defineN_TXTADDR(x)(N_MAGIC(x)==QMAGIC?TARGET_PAGE_SIZE:0)#defineN_DATOFF(x)(N_TXTOFF(x)+(x).a_text)#define_N_SEGMENT_ROUND(x)(((x)+TARGET_PAGE_SIZE-1)&~(TARGET_PAGE_SIZE-1))#define_N_TXTENDADDR(x)(N_TXTADDR(x)+(x).a_text)#defineN_DATADDR(x)\(N_MAGIC(x)==OMAGIC?(_N_TXTENDADDR(x))\:(_N_SEGMENT_ROUND(_N_TXTENDADDR(x))))
#defineZALLOC_ALIGNMENT16staticvoid*zalloc(void*x,unsigneditems,unsignedsize){void*p;size*=items;size=(size+ZALLOC_ALIGNMENT-1)&~(ZALLOC_ALIGNMENT-1);p=qemu_malloc(size);return(p);}staticvoidzfree(void*x,void*addr,unsignednb){qemu_free(addr);}#defineHEAD_CRC2#defineEXTRA_FIELD4#defineORIG_NAME8#defineCOMMENT0x10#defineRESERVED0xe0#defineDEFLATED8/*Thisisthemaximuminuboot,soifauImageoverflowsthis,itwould*overflowonrealhardwaretoo.*/#defineUBOOT_MAX_GUNZIP_BYTES0x800000staticssize_tgunzip(void*dst,size_tdstlen,uint8_t*src,size_tsrclen){z_streams;ssize_tdstbytes;intr,i,flags;/* skip header */i=10;flags=src[3];if(src[2]!=DEFLATED||(flags&RESERVED)!=0){puts("Error: Bad gzipped data\n");return-1;}if((flags&EXTRA_FIELD)!=0)i=12+src[10]+(src[11]<<8);if((flags&ORIG_NAME)!=0)while(src[i++]!=0);if((flags&COMMENT)!=0)while(src[i++]!=0);if((flags&HEAD_CRC)!=0)i+=2;if(i>=srclen){puts("Error: gunzip out of data in header\n");return-1;}s.zalloc=zalloc;s.zfree=(free_func)zfree;r=inflateInit2(&s,-MAX_WBITS);if(r!=Z_OK){printf("Error: inflateInit2() returned %d\n",r);return(-1);}s.next_in=src+i;s.avail_in=srclen-i;s.next_out=dst;s.avail_out=dstlen;r=inflate(&s,Z_FINISH);if(r!=Z_OK&&r!=Z_STREAM_END){printf("Error: inflate() returned %d\n",r);return-1;}dstbytes=s.next_out-(unsignedchar*)dst;inflateEnd(&s);returndstbytes;}
switch(hdr->ih_comp){caseIH_COMP_NONE:caseIH_COMP_GZIP:break;default:fprintf(stderr,"Unable to load u-boot images with compression type %d\n",hdr->ih_comp);
if(hdr->ih_comp==IH_COMP_GZIP){uint8_t*compressed_data;size_tmax_bytes;ssize_tbytes;compressed_data=data;max_bytes=UBOOT_MAX_GUNZIP_BYTES;data=qemu_malloc(max_bytes);bytes=gunzip(data,max_bytes,compressed_data,hdr->ih_size);qemu_free(compressed_data);if(bytes<0){fprintf(stderr,"Unable to decompress gzipped image!\n");gotoout;}hdr->ih_size=bytes;}