A bootloader for Android used on various devices powered by Qualcomm Snapdragon chips:
https://en.wikipedia.org/wiki/Devices_using_Qualcomm_Snapdragon_processors
Although not all of the Snapdragon based Android devices use this particular bootloader format, it is known that devices with the following chips have used it (example devices are given for each chip):
APQ8064 (devices)
MSM8974AA (devices)
MSM8992 (devices)
APQ8064-1AA (devices)
MSM8996 Pro-AB (devices)
MSM8998 (devices)
(*)
bootloader_size
is equal to the size of the whole file (not just img_bodies
as usual).
(**)
There are some data after the end of img_bodies
.
On the other hand, devices with these chips do not use this format:
APQ8084 (devices)
MSM8994 (devices)
The bootloader-*.img
samples referenced above originally come from factory
images packed in ZIP archives that can be found on the page Factory Images
for Nexus and Pixel Devices on
the Google Developers site. Note that the codenames on that page may be
different than the ones that are written in the list above. That's because the
Google page indicates ROM codenames in headings (e.g. "occam" for Nexus 4)
but the above list uses model codenames (e.g. "mako" for Nexus 4) because
that is how the original bootloader-*.img
files are identified. For most
devices, however, these code names are the same.
This page hosts a formal specification of Qualcomm Snapdragon (MSM) bootloader.img format using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
use strict;
use warnings;
use IO::KaitaiStruct 0.009_000;
use Encode;
########################################################################
package AndroidBootldrQcom;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{magic} = $self->{_io}->read_bytes(8);
$self->{num_images} = $self->{_io}->read_u4le();
$self->{ofs_img_bodies} = $self->{_io}->read_u4le();
$self->{bootloader_size} = $self->{_io}->read_u4le();
$self->{img_headers} = ();
my $n_img_headers = $self->num_images();
for (my $i = 0; $i < $n_img_headers; $i++) {
push @{$self->{img_headers}}, AndroidBootldrQcom::ImgHeader->new($self->{_io}, $self, $self->{_root});
}
}
sub img_bodies {
my ($self) = @_;
return $self->{img_bodies} if ($self->{img_bodies});
my $_pos = $self->{_io}->pos();
$self->{_io}->seek($self->ofs_img_bodies());
$self->{img_bodies} = ();
my $n_img_bodies = $self->num_images();
for (my $i = 0; $i < $n_img_bodies; $i++) {
push @{$self->{img_bodies}}, AndroidBootldrQcom::ImgBody->new($self->{_io}, $self, $self->{_root});
}
$self->{_io}->seek($_pos);
return $self->{img_bodies};
}
sub magic {
my ($self) = @_;
return $self->{magic};
}
sub num_images {
my ($self) = @_;
return $self->{num_images};
}
sub ofs_img_bodies {
my ($self) = @_;
return $self->{ofs_img_bodies};
}
sub bootloader_size {
my ($self) = @_;
return $self->{bootloader_size};
}
sub img_headers {
my ($self) = @_;
return $self->{img_headers};
}
########################################################################
package AndroidBootldrQcom::ImgHeader;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{name} = Encode::decode("ASCII", IO::KaitaiStruct::Stream::bytes_terminate($self->{_io}->read_bytes(64), 0, 0));
$self->{len_body} = $self->{_io}->read_u4le();
}
sub name {
my ($self) = @_;
return $self->{name};
}
sub len_body {
my ($self) = @_;
return $self->{len_body};
}
########################################################################
package AndroidBootldrQcom::ImgBody;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{body} = $self->{_io}->read_bytes($self->img_header()->len_body());
}
sub img_header {
my ($self) = @_;
return $self->{img_header} if ($self->{img_header});
$self->{img_header} = @{$self->_root()->img_headers()}[$self->idx()];
return $self->{img_header};
}
sub body {
my ($self) = @_;
return $self->{body};
}
sub idx {
my ($self) = @_;
return $self->{idx};
}
1;