Path: csiph.com!newsfeed.hal-mli.net!feeder3.hal-mli.net!newsfeed.hal-mli.net!feeder1.hal-mli.net!nntp.club.cc.cmu.edu!micro-heart-of-gold.mit.edu!bloom-beacon.mit.edu!bloom-beacon.mit.edu!panix!not-for-mail From: Grant Edwards Newsgroups: comp.lang.python Subject: Re: Unpacking U-Boot image file Date: Fri, 11 Apr 2014 16:02:36 +0000 (UTC) Organization: PANIX Public Access Internet and UNIX, NYC Lines: 129 Message-ID: References: <6ed343e7-fa02-426a-a75f-3e1d164a6a61@googlegroups.com> NNTP-Posting-Host: dsl.comtrol.com X-Trace: reader1.panix.com 1397232156 4542 64.122.56.22 (11 Apr 2014 16:02:36 GMT) X-Complaints-To: abuse@panix.com NNTP-Posting-Date: Fri, 11 Apr 2014 16:02:36 +0000 (UTC) User-Agent: slrn/1.0.1 (Linux) Xref: csiph.com comp.lang.python:70153 On 2014-04-10, Rhodri James wrote: > On Wed, 09 Apr 2014 18:18:56 +0100, Rustom Mody wrote: >> On Wednesday, April 9, 2014 9:36:40 PM UTC+5:30, trewio wrote: >> >>> How to extract files from U-Boot image file, LZMA-compressed? >>> >>> Is there a Python script that can do this properly? >> >> For lzma theres this (recent) python library >> https://docs.python.org/dev/library/lzma.html >> >> Though you might just be better off with the command-line xz unxz etc >> >> After that.. whats the U-boot format? > > The Fine Manual (http://www.denx.de/wiki/view/DULG/UBootImages) isn't very > forthcoming, sadly; > > "U-Boot operates on "image" files which can be basically anything, > preceeded by a special header; see the definitions in include/image.h for > details; basically, the header defines the following image properties > > * Target Operating System > * Target CPU Architecture > * Compression Type > * Load Address > * Entry Point > * Image Name > * Image Timestamp" > > I suspect taking this apart may be a little involved. Not really. For the format you're talking about (single-file uImage), you can extract the data like so: data = open("foobar.uImage","rb").read()[64:] Then just uncompress 'data' as desired. If you want to look at individual fields in the heaer, here's the structure: #define IH_MAGIC 0x27051956 /* Image Magic Number */ #define IH_NMLEN 32 /* Image Name Length */ typedef struct image_header { uint32_t ih_magic; /* Image Header Magic Number */ uint32_t ih_hcrc; /* Image Header CRC Checksum */ uint32_t ih_time; /* Image Creation Timestamp */ uint32_t ih_size; /* Image Data Size */ uint32_t ih_load; /* Data Load Address */ uint32_t ih_ep; /* Entry Point Address */ uint32_t ih_dcrc; /* Image Data CRC Checksum */ uint8_t ih_os; /* Operating System */ uint8_t ih_arch; /* CPU architecture */ uint8_t ih_type; /* Image Type */ uint8_t ih_comp; /* Compression Type */ uint8_t ih_name[IH_NMLEN]; /* Image Name */ } image_header_t; Header fields are all in network byte order (bit-endian). However, there's also a "multi-file" uImage format that I suspect is what the OP is referring to (since he says he needs to extract "files" from a uImage file). http://www.isysop.com/unpacking-and-repacking-u-boot-uimage-files/ In that case, the "Image Type" field will be set to 4, and the 'data' field starts with a list of 32-bit image size values (network byte order, terminated by 0x00000000). That list is then followed by the image data. Here's a Python 2.7 program that reads the uImage header, prints some stuff and then reads the data for the image(s). What to _do_ with the data for the image(s) is left as an exercise for the gentle reader. -------------------------------------8<------------------------------------- #!/usr/bin/python import sys,struct f = open(sys.argv[1],"rb") (ih_magic, ih_hcrc, ih_time, ih_size, ih_load, ih_ep, ih_dcrc, ih_os, ih_arch, ih_type, ih_comp, ih_name) \ = struct.unpack("!IIIIIIIBBBB32s",f.read(64)) print "magic=%08x type=%d size=%d name='%s'" % (ih_magic, ih_type, ih_size, ih_name) if ih_type == 4: # multi-file: read image lengths from data imagesizes = [] while 1: size, = struct.unpack("!I",f.read(4)) if size == 0: break imagesizes.append(size) else: # single-file imagesizes = [ih_size] print imagesizes images = [f.read(size) for size in imagesizes] print [len(image) for image in images] extradata = f.read() if extradata: print "%d bytes of extra data" % len(extradata) -------------------------------------8<------------------------------------- -- Grant Edwards grant.b.edwards Yow! The Korean War must at have been fun. gmail.com