diff mbox

[U-Boot,v4] socfpga: Add socfpga preloader signing to mkimage

Message ID 1393194939-29786-1-git-send-email-cdhmanning@gmail.com
State Changes Requested
Delegated to: Wolfgang Denk
Headers show

Commit Message

Charles Manning Feb. 23, 2014, 10:35 p.m. UTC
Like many platforms, the Altera socfpga platform requires that the
preloader be "signed" in a certain way or the built-in boot ROM will
not boot the code.

This change automatically creates an appropriately signed preloader
from an SPL image.

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
---

Changes for v3:
 - Fix some coding style issues.
 - Move from a standalone tool to the mkimgae framework.

Changes for v4:
 - Fix more coding style issues.
 - Fix typos in Makefile.
 - Rebase on master (previous version was not on master, but on a 
   working socfpga branch).

Note: Building a SOCFPGA preloader will currently not produe a working
image, but that is due to issues in building SPL, not in this signer.

 common/image.c       |    1 +
 include/image.h      |    1 +
 spl/Makefile         |    8 ++
 tools/Makefile       |    1 +
 tools/imagetool.c    |    2 +
 tools/imagetool.h    |    1 +
 tools/socfpgaimage.c |  365 ++++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 379 insertions(+)
 create mode 100644 tools/socfpgaimage.c

Comments

Wolfgang Denk Feb. 24, 2014, 6:48 a.m. UTC | #1
Dear Charles,

In message <1393194939-29786-1-git-send-email-cdhmanning@gmail.com> you wrote:
> Like many platforms, the Altera socfpga platform requires that the
> preloader be "signed" in a certain way or the built-in boot ROM will
> not boot the code.
> 
> This change automatically creates an appropriately signed preloader
> from an SPL image.
> 
> Signed-off-by: Charles Manning <cdhmanning@gmail.com>
> ---
> 
> Changes for v3:
>  - Fix some coding style issues.
>  - Move from a standalone tool to the mkimgae framework.
> 
> Changes for v4:
>  - Fix more coding style issues.
>  - Fix typos in Makefile.
>  - Rebase on master (previous version was not on master, but on a 
>    working socfpga branch).

There may be perfectly valid reasons why you might decide to ingore a
review comments - sch comments may be wrong, too, after all.  But in
such a case it is always a good idea to provide feedback to the
reviewer why you decided not to follow his advice.  Otherwise he might
think you just missed or ignored the comment.

And this is what is happeneing (again) in your patch...

> diff --git a/spl/Makefile b/spl/Makefile
> index bf98024..90faaa6 100644
> --- a/spl/Makefile
> +++ b/spl/Makefile
> @@ -181,6 +181,14 @@ $(objtree)/SPL : $(obj)/u-boot-spl.bin
>  
>  ALL-y	+= $(obj)/$(SPL_BIN).bin
>  
> +$(OBJTREE)/socfpga-signed-preloader.bin: $(obj)/u-boot-spl.bin
> +	$(OBJTREE)/tools/mkimage -T socfpgaimage -d $< $@
> +
> +

One blank line is sufficient.

I asked before:  "socfpga-signed-preloader.bin" is a terribly long
name.  Can we find a better one?

> +ifdef CONFIG_SOCFPGA
> +ALL-y += $(OBJTREE)/socfpga-signed-preloader.bin
> +endif

I asked before: Can we not use "ALL-$(CONFIG_SOCFPGA)" and avoid the
ifdef ?

> + * Reference doc http://www.altera.com.cn/literature/hb/cyclone-v/cv_5400A.pdf
> + * Note this doc is not entirely accurate.

I aseked before: Would you care to explain the errors in the document
that might cause problems to the reader?

Noting that something contains errors without mentioning what these
are is really not helpful.

> + * This uses the CRC32 calc out of the well known Apple
> + * crc32.c code. CRC32 algorithms do not produce the same results.
> + * We need this one. Sorry about the coade bloat.

Both Gerhard and me asked before: Why exactly do we need another
implementation of CRC32.  We already have some - why cannot we use
these?

> + * Copyright for the CRC code:
> + *
> + * COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
> + *  code or tables extracted from it, as desired without restriction.

I asked before:  Please provide _exact_ reference. See 
http://www.denx.de/wiki/view/U-Boot/Patches#Attributing_Code_Copyrights_Sign
for instructions how to do this.

I also commented before: If you really need this copied code (i. e.
you canot use one of the already existing implementations of CRC32 -
which I seriously doubt), then better move this into a separate file,
and assign a separate license ID tag for it.


I also asked this before: I cannot find a license ID tag in your new
code. Please add.

> +/* To work in with the mkimage framework, we do some ugly stuff...
> + *
> + * First we prepend a fake header big enough to make the file 64k.
> + * When set_header is called, we fix this up by moving the image
> + * around in the buffer.
> + */

Also asked before: Incorrect multiline comment style. Please fix
globally.



It turns out that you basically ignored nearly ALL of trhe review
comments which I made before, twice.


It is an exhausting experience to deal with your patches :-(


Wolfgang Denk
Charles Manning Feb. 24, 2014, 7:18 p.m. UTC | #2
Hello Wolfgang
On Monday 24 February 2014 19:48:36 Wolfgang Denk wrote:
> Dear Charles,
>
> In message <1393194939-29786-1-git-send-email-cdhmanning@gmail.com> you 
wrote:
> > Like many platforms, the Altera socfpga platform requires that the
> > preloader be "signed" in a certain way or the built-in boot ROM will
> > not boot the code.
> >
> > This change automatically creates an appropriately signed preloader
> > from an SPL image.
> >
> > Signed-off-by: Charles Manning <cdhmanning@gmail.com>
> > ---
> >
> > Changes for v3:
> >  - Fix some coding style issues.
> >  - Move from a standalone tool to the mkimgae framework.
> >
> > Changes for v4:
> >  - Fix more coding style issues.
> >  - Fix typos in Makefile.
> >  - Rebase on master (previous version was not on master, but on a
> >    working socfpga branch).
>
> There may be perfectly valid reasons why you might decide to ingore a
> review comments - sch comments may be wrong, too, after all.  But in
> such a case it is always a good idea to provide feedback to the
> reviewer why you decided not to follow his advice.  Otherwise he might
> think you just missed or ignored the comment.

I am sorry, I must have missed some of the comments. I have intended to 
implement them all, except one by Gerhard.

>
> And this is what is happeneing (again) in your patch...
>
> > diff --git a/spl/Makefile b/spl/Makefile
> > index bf98024..90faaa6 100644
> > --- a/spl/Makefile
> > +++ b/spl/Makefile
> > @@ -181,6 +181,14 @@ $(objtree)/SPL : $(obj)/u-boot-spl.bin
> >
> >  ALL-y	+= $(obj)/$(SPL_BIN).bin
> >
> > +$(OBJTREE)/socfpga-signed-preloader.bin: $(obj)/u-boot-spl.bin
> > +	$(OBJTREE)/tools/mkimage -T socfpgaimage -d $< $@
> > +
> > +
>
> One blank line is sufficient.

Ok, a blank line. I can delete that.

>
> I asked before:  "socfpga-signed-preloader.bin" is a terribly long
> name.  Can we find a better one?
>
> > +ifdef CONFIG_SOCFPGA
> > +ALL-y += $(OBJTREE)/socfpga-signed-preloader.bin
> > +endif
>
> I asked before: Can we not use "ALL-$(CONFIG_SOCFPGA)" and avoid the
> ifdef ?

I am sorry, I had developed this code in a different (older) branch where 
socfpga actually works. It is broken in master.

This I shall fix.

>
> > + * Reference doc
> > http://www.altera.com.cn/literature/hb/cyclone-v/cv_5400A.pdf + * Note
> > this doc is not entirely accurate.
>
> I aseked before: Would you care to explain the errors in the document
> that might cause problems to the reader?
>
> Noting that something contains errors without mentioning what these
> are is really not helpful.

Ok, I shall mention the errors pertinent to the code. Other errors I shall 
ignore.

>
> > + * This uses the CRC32 calc out of the well known Apple
> > + * crc32.c code. CRC32 algorithms do not produce the same results.
> > + * We need this one. Sorry about the coade bloat.
>
> Both Gerhard and me asked before: Why exactly do we need another
> implementation of CRC32.  We already have some - why cannot we use
> these?

Well I would have thought that obvious from the comment I put in the code, but 
email is an imperfect communications medium, so I shall explain in further 
detail here.

As I am sure you are aware, there are many different crc32 calculations. 
Indeed Wikipedia lists 5 and there are most likely others.

Even when they use the same polynomial, they give differences when you stuff 
the bits through the shift register lsb-first or msb-first.

Now from what I see looking through the u-boot lib/ directory u-boot provides 
just one crc32 version - Adler (and a bit flipped version thereof for use by 
jffs2). If there are others I did not see them.

Now as I expect you are aware, the purpose of a signer is to massage the code 
so that it is in a form that the boot ROM accepts. One of those criteria is 
that the crc in the code matches the crc the boot ROM is expecting. If not, 
the boot ROM refuses to execute the code.

It would be nice to use the Adler code. Indeed this is my favourite crc. 
However, this is not what the boot ROM wants.

The boot ROM does not enter into rational discussions, so we must, 
unfortunately, bow to its whims. If it wants a different CRC calculation then 
we must supply it.

I did much experimentation to find the crc that worked. I tried the zlib crc - 
no luck.  I tried different many things until I found something that worked.

>
> > + * Copyright for the CRC code:
> > + *
> > + * COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
> > + *  code or tables extracted from it, as desired without restriction.
>
> I asked before:  Please provide _exact_ reference. See
> http://www.denx.de/wiki/view/U-Boot/Patches#Attributing_Code_Copyrights_Sig
>n for instructions how to do this.

As it was, I had attributed this incorrectly. This is a file I generated 
myself, though I had used this as a reference during my research. The values 
will look the same as some other code floating out there, but that is because 
that is the way things have to be.

I shall fix this wen I make another file.


>
> I also commented before: If you really need this copied code (i. e.
> you canot use one of the already existing implementations of CRC32 -
> which I seriously doubt), then better move this into a separate file,
> and assign a separate license ID tag for it.

You say "already exiting implementations". I see only one: lib/crc32.c. 
Perhaps I am not looking in the right place?

I shall split this code out and call it alt_crc32 and put it in lib with one 
of those proxy files in tools.

>
>
> I also asked this before: I cannot find a license ID tag in your new
> code. Please add.

Ok.


>
> > +/* To work in with the mkimage framework, we do some ugly stuff...
> > + *
> > + * First we prepend a fake header big enough to make the file 64k.
> > + * When set_header is called, we fix this up by moving the image
> > + * around in the buffer.
> > + */
>
> Also asked before: Incorrect multiline comment style. Please fix
> globally.

Ok.

I am sorry I missed some of your comments earlier.

Regards

Charles
Charles Manning Feb. 24, 2014, 9:03 p.m. UTC | #3
Hello Wolfgang

I have some further observations to my last email...

Your input would be vastly appreciated.

Please see below.


On Tue, Feb 25, 2014 at 8:18 AM, Charles Manning <cdhmanning@gmail.com>wrote:

> Hello Wolfgang
> On Monday 24 February 2014 19:48:36 Wolfgang Denk wrote:
> > Dear Charles,
> >
> > In message <1393194939-29786-1-git-send-email-cdhmanning@gmail.com> you
> wrote:
> > > Like many platforms, the Altera socfpga platform requires that the
> > > preloader be "signed" in a certain way or the built-in boot ROM will
> > > not boot the code.
> > >
> > > This change automatically creates an appropriately signed preloader
> > > from an SPL image.
> > >
> > > Signed-off-by: Charles Manning <cdhmanning@gmail.com>
> > > ---
> > >
> > > Changes for v3:
> > >  - Fix some coding style issues.
> > >  - Move from a standalone tool to the mkimgae framework.
> > >
> > > Changes for v4:
> > >  - Fix more coding style issues.
> > >  - Fix typos in Makefile.
> > >  - Rebase on master (previous version was not on master, but on a
> > >    working socfpga branch).
> >
> > There may be perfectly valid reasons why you might decide to ingore a
> > review comments - sch comments may be wrong, too, after all.  But in
> > such a case it is always a good idea to provide feedback to the
> > reviewer why you decided not to follow his advice.  Otherwise he might
> > think you just missed or ignored the comment.
>
> I am sorry, I must have missed some of the comments. I have intended to
> implement them all, except one by Gerhard.
>
> >
> > And this is what is happeneing (again) in your patch...
> >
> > > diff --git a/spl/Makefile b/spl/Makefile
> > > index bf98024..90faaa6 100644
> > > --- a/spl/Makefile
> > > +++ b/spl/Makefile
> > > @@ -181,6 +181,14 @@ $(objtree)/SPL : $(obj)/u-boot-spl.bin
> > >
> > >  ALL-y      += $(obj)/$(SPL_BIN).bin
> > >
> > > +$(OBJTREE)/socfpga-signed-preloader.bin: $(obj)/u-boot-spl.bin
> > > +   $(OBJTREE)/tools/mkimage -T socfpgaimage -d $< $@
> > > +
> > > +
> >
> > One blank line is sufficient.
>
> Ok, a blank line. I can delete that.
>
> >
> > I asked before:  "socfpga-signed-preloader.bin" is a terribly long
> > name.  Can we find a better one?
> >
> > > +ifdef CONFIG_SOCFPGA
> > > +ALL-y += $(OBJTREE)/socfpga-signed-preloader.bin
> > > +endif
> >
> > I asked before: Can we not use "ALL-$(CONFIG_SOCFPGA)" and avoid the
> > ifdef ?
>

> I am sorry, I had developed this code in a different (older) branch where
> socfpga actually works. It is broken in master.
>
> This I shall fix.
>

I can certainly avoid the ifdef, but there is already another one three
lines down
for the SAMSUNG case:

 ifdef CONFIG_SOCFPGA
ALL-y += $(OBJTREE)/socfpga-signed-preloader.bin
endif

ifdef CONFIG_SAMSUNG
ALL-y    += $(obj)/$(BOARD)-spl.bin
endif

It seems odd to me that you would want different conventions in the same
Makefile,
but if that is what you want then that is what you will get.



>
> >
> > > + * Reference doc
> > > http://www.altera.com.cn/literature/hb/cyclone-v/cv_5400A.pdf + * Note
> > > this doc is not entirely accurate.
> >
> > I aseked before: Would you care to explain the errors in the document
> > that might cause problems to the reader?
> >
> > Noting that something contains errors without mentioning what these
> > are is really not helpful.
>
> Ok, I shall mention the errors pertinent to the code. Other errors I shall
> ignore.
>
> >
> > > + * This uses the CRC32 calc out of the well known Apple
> > > + * crc32.c code. CRC32 algorithms do not produce the same results.
> > > + * We need this one. Sorry about the coade bloat.
> >
> > Both Gerhard and me asked before: Why exactly do we need another
> > implementation of CRC32.  We already have some - why cannot we use
> > these?
>
> Well I would have thought that obvious from the comment I put in the code,
> but
> email is an imperfect communications medium, so I shall explain in further
> detail here.
>
> As I am sure you are aware, there are many different crc32 calculations.
> Indeed Wikipedia lists 5 and there are most likely others.
>
> Even when they use the same polynomial, they give differences when you
> stuff
> the bits through the shift register lsb-first or msb-first.
>
> Now from what I see looking through the u-boot lib/ directory u-boot
> provides
> just one crc32 version - Adler (and a bit flipped version thereof for use
> by
> jffs2). If there are others I did not see them.
>
> Now as I expect you are aware, the purpose of a signer is to massage the
> code
> so that it is in a form that the boot ROM accepts. One of those criteria is
> that the crc in the code matches the crc the boot ROM is expecting. If not,
> the boot ROM refuses to execute the code.
>
> It would be nice to use the Adler code. Indeed this is my favourite crc.
> However, this is not what the boot ROM wants.
>
> The boot ROM does not enter into rational discussions, so we must,
> unfortunately, bow to its whims. If it wants a different CRC calculation
> then
> we must supply it.
>
> I did much experimentation to find the crc that worked. I tried the zlib
> crc -
> no luck.  I tried different many things until I found something that
> worked.
>

The actual table values I am using are also found in lib/bzlib_crctable.c

This is, however, not exposed but is a private thing within bzlib.

The best choice would possibly be to expose this with a new crc function,
but that means dragging bzlib (or parts thereof) into mkimage or at least
putting "hooks" into bzlib that were never intended to be there.

The alternative is to maybe just add a new alt_crc.c to lib.


>
> >
> > > + * Copyright for the CRC code:
> > > + *
> > > + * COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
> > > + *  code or tables extracted from it, as desired without restriction.
> >
> > I asked before:  Please provide _exact_ reference. See
> >
> http://www.denx.de/wiki/view/U-Boot/Patches#Attributing_Code_Copyrights_Sig
> >n for instructions how to do this.
>
> As it was, I had attributed this incorrectly. This is a file I generated
> myself, though I had used this as a reference during my research. The
> values
> will look the same as some other code floating out there, but that is
> because
> that is the way things have to be.
>
> I shall fix this wen I make another file.
>
>
> >
> > I also commented before: If you really need this copied code (i. e.
> > you canot use one of the already existing implementations of CRC32 -
> > which I seriously doubt), then better move this into a separate file,
> > and assign a separate license ID tag for it.
>
> You say "already exiting implementations". I see only one: lib/crc32.c.
> Perhaps I am not looking in the right place?
>
> I shall split this code out and call it alt_crc32 and put it in lib with
> one
> of those proxy files in tools.
>
> >
> >
> > I also asked this before: I cannot find a license ID tag in your new
> > code. Please add.
>
> Ok.
>
>
> >
> > > +/* To work in with the mkimage framework, we do some ugly stuff...
> > > + *
> > > + * First we prepend a fake header big enough to make the file 64k.
> > > + * When set_header is called, we fix this up by moving the image
> > > + * around in the buffer.
> > > + */
> >
> > Also asked before: Incorrect multiline comment style. Please fix
> > globally.
>
> Ok.
>
> I am sorry I missed some of your comments earlier.
>
> Regards
>
> Charles
>
Wolfgang Denk Feb. 27, 2014, 9:19 p.m. UTC | #4
Dear Charles,

In message <CAE21AQp2GSPedrDakio1wPa3vGTwjd-3D1wSQM0WhG9r-8Bzcg@mail.gmail.com> you wrote:
> 
> > > I asked before: Can we not use "ALL-$(CONFIG_SOCFPGA)" and avoid the
> > > ifdef ?
...
> I can certainly avoid the ifdef, but there is already another one three
> lines down
> for the SAMSUNG case:
> 
>  ifdef CONFIG_SOCFPGA
> ALL-y += $(OBJTREE)/socfpga-signed-preloader.bin
> endif
> 
> ifdef CONFIG_SAMSUNG
> ALL-y    += $(obj)/$(BOARD)-spl.bin
> endif
> 
> It seems odd to me that you would want different conventions in the same
> Makefile,
> but if that is what you want then that is what you will get.

Existing poor code should not be used as reference for adding new bad
code.  If possible, it should be imprived -patches are welcome.  In any
case, please avoid the issues in new code.

Best regards,

Wolfgang Denk
Wolfgang Denk Feb. 27, 2014, 9:23 p.m. UTC | #5
Dear Charles,

sorry, I only send part of the message. Here is the rest.

In message <CAE21AQp2GSPedrDakio1wPa3vGTwjd-3D1wSQM0WhG9r-8Bzcg@mail.gmail.com> you wrote:
> 
> > > Both Gerhard and me asked before: Why exactly do we need another
> > > implementation of CRC32.  We already have some - why cannot we use
> > > these?
...
> The actual table values I am using are also found in lib/bzlib_crctable.c

So could you use the bzlib implementation for your purposes?

> This is, however, not exposed but is a private thing within bzlib.
> 
> The best choice would possibly be to expose this with a new crc function,
> but that means dragging bzlib (or parts thereof) into mkimage or at least
> putting "hooks" into bzlib that were never intended to be there.
> 
> The alternative is to maybe just add a new alt_crc.c to lib.

Code duplication is always bad.  Please factor out common code parts.

> > > > + * Copyright for the CRC code:
> > > > + *
> > > > + * COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
> > > > + *  code or tables extracted from it, as desired without restriction.
> > >
> > > I asked before:  Please provide _exact_ reference. See
...

Exact reference includes some URL plus version id, etc.

> > > I also commented before: If you really need this copied code (i. e.
> > > you canot use one of the already existing implementations of CRC32 -
> > > which I seriously doubt), then better move this into a separate file,
> > > and assign a separate license ID tag for it.
> >
> > You say "already exiting implementations". I see only one: lib/crc32.c.
> > Perhaps I am not looking in the right place?
> >
> > I shall split this code out and call it alt_crc32 and put it in lib with
> > one
> > of those proxy files in tools.

"alt" is a really bad name - you mentioned yourself that ther eis not
only one alternative, so please rather use a descriptive name.


Best regards,

Wolfgang Denk
Charles Manning Feb. 27, 2014, 9:46 p.m. UTC | #6
> > I can certainly avoid the ifdef, but there is already another one three
> > lines down
> > for the SAMSUNG case:
> >
> >  ifdef CONFIG_SOCFPGA
> > ALL-y += $(OBJTREE)/socfpga-signed-preloader.bin
> > endif
> >
> > ifdef CONFIG_SAMSUNG
> > ALL-y    += $(obj)/$(BOARD)-spl.bin
> > endif
> >
> > It seems odd to me that you would want different conventions in the same
> > Makefile,
> > but if that is what you want then that is what you will get.
>
> Existing poor code should not be used as reference for adding new bad
> code.  If possible, it should be imprived -patches are welcome.  In any
> case, please avoid the issues in new code.

Thank you for that, though it is not obvious which is poor code and which is 
good code and sometimes one must follow what exists for guidance.

I have cleared this up in the latest version that I posted.

-- Charles
Charles Manning Feb. 27, 2014, 9:52 p.m. UTC | #7
On Friday 28 February 2014 10:23:11 Wolfgang Denk wrote:
> Dear Charles,
>
> sorry, I only send part of the message. Here is the rest.
>
> In message 
<CAE21AQp2GSPedrDakio1wPa3vGTwjd-3D1wSQM0WhG9r-8Bzcg@mail.gmail.com> you 
wrote:
> > > > Both Gerhard and me asked before: Why exactly do we need another
> > > > implementation of CRC32.  We already have some - why cannot we use
> > > > these?
>
> ...
>
> > The actual table values I am using are also found in lib/bzlib_crctable.c
>
> So could you use the bzlib implementation for your purposes?
>
> > This is, however, not exposed but is a private thing within bzlib.
> >
> > The best choice would possibly be to expose this with a new crc function,
> > but that means dragging bzlib (or parts thereof) into mkimage or at least
> > putting "hooks" into bzlib that were never intended to be there.
> >
> > The alternative is to maybe just add a new alt_crc.c to lib.
>
> Code duplication is always bad.  Please factor out common code parts.

Ok,  I will write a small wrapper thing that accesses the bzlib table.

That table will now be compiled in if you use either bzlib or the alternative 
crc32. 

Does that sound OK?

>
> > > > > + * Copyright for the CRC code:
> > > > > + *
> > > > > + * COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
> > > > > + *  code or tables extracted from it, as desired without
> > > > > restriction.
> > > >
> > > > I asked before:  Please provide _exact_ reference. See
>
> ...
>
> Exact reference includes some URL plus version id, etc.

That stuff is now gone

>
> > > > I also commented before: If you really need this copied code (i. e.
> > > > you canot use one of the already existing implementations of CRC32 -
> > > > which I seriously doubt), then better move this into a separate file,
> > > > and assign a separate license ID tag for it.
> > >
> > > You say "already exiting implementations". I see only one: lib/crc32.c.
> > > Perhaps I am not looking in the right place?
> > >
> > > I shall split this code out and call it alt_crc32 and put it in lib
> > > with one
> > > of those proxy files in tools.
>
> "alt" is a really bad name - you mentioned yourself that ther eis not
> only one alternative, so please rather use a descriptive name.

Is bzlib_crc32 Ok?

Thank you for your feedback.

-- CHarles
diff mbox

Patch

diff --git a/common/image.c b/common/image.c
index 9c6bec5..e7dc8cc 100644
--- a/common/image.c
+++ b/common/image.c
@@ -135,6 +135,7 @@  static const table_entry_t uimage_type[] = {
 	{	IH_TYPE_PBLIMAGE,   "pblimage",   "Freescale PBL Boot Image",},
 	{	IH_TYPE_RAMDISK,    "ramdisk",	  "RAMDisk Image",	},
 	{	IH_TYPE_SCRIPT,     "script",	  "Script",		},
+	{	IH_TYPE_SOCFPGAIMAGE,  "socfpgaimage",  "Altera SOCFPGA preloader",},
 	{	IH_TYPE_STANDALONE, "standalone", "Standalone Program", },
 	{	IH_TYPE_UBLIMAGE,   "ublimage",   "Davinci UBL image",},
 	{	IH_TYPE_MXSIMAGE,   "mxsimage",   "Freescale MXS Boot Image",},
diff --git a/include/image.h b/include/image.h
index 6afd57b..bde31d9 100644
--- a/include/image.h
+++ b/include/image.h
@@ -215,6 +215,7 @@  struct lmb;
 #define IH_TYPE_KERNEL_NOLOAD	14	/* OS Kernel Image, can run from any load address */
 #define IH_TYPE_PBLIMAGE	15	/* Freescale PBL Boot Image	*/
 #define IH_TYPE_MXSIMAGE	16	/* Freescale MXSBoot Image	*/
+#define IH_TYPE_SOCFPGAIMAGE	17	/* Altera SOCFPGA Preloader	*/
 
 /*
  * Compression Types
diff --git a/spl/Makefile b/spl/Makefile
index bf98024..90faaa6 100644
--- a/spl/Makefile
+++ b/spl/Makefile
@@ -181,6 +181,14 @@  $(objtree)/SPL : $(obj)/u-boot-spl.bin
 
 ALL-y	+= $(obj)/$(SPL_BIN).bin
 
+$(OBJTREE)/socfpga-signed-preloader.bin: $(obj)/u-boot-spl.bin
+	$(OBJTREE)/tools/mkimage -T socfpgaimage -d $< $@
+
+
+ifdef CONFIG_SOCFPGA
+ALL-y += $(OBJTREE)/socfpga-signed-preloader.bin
+endif
+
 ifdef CONFIG_SAMSUNG
 ALL-y	+= $(obj)/$(BOARD)-spl.bin
 endif
diff --git a/tools/Makefile b/tools/Makefile
index dcd49f8..59ff8d3 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -85,6 +85,7 @@  dumpimage-mkimage-objs := aisimage.o \
 			os_support.o \
 			pblimage.o \
 			sha1.o \
+			socfpgaimage.o \
 			ublimage.o \
 			$(LIBFDT_OBJS) \
 			$(RSA_OBJS-y)
diff --git a/tools/imagetool.c b/tools/imagetool.c
index 29d2189..1ef20b1 100644
--- a/tools/imagetool.c
+++ b/tools/imagetool.c
@@ -45,6 +45,8 @@  void register_image_tool(imagetool_register_t image_register)
 	init_ubl_image_type();
 	/* Init Davinci AIS support */
 	init_ais_image_type();
+	/* Init Altera SOCFPGA support */
+	init_socfpga_image_type();
 }
 
 /*
diff --git a/tools/imagetool.h b/tools/imagetool.h
index c2c9aea..c4833b1 100644
--- a/tools/imagetool.h
+++ b/tools/imagetool.h
@@ -167,6 +167,7 @@  void init_mxs_image_type(void);
 void init_fit_image_type(void);
 void init_ubl_image_type(void);
 void init_omap_image_type(void);
+void init_socfpga_image_type(void);
 
 void pbl_load_uboot(int fd, struct image_tool_params *mparams);
 
diff --git a/tools/socfpgaimage.c b/tools/socfpgaimage.c
new file mode 100644
index 0000000..ca4369c
--- /dev/null
+++ b/tools/socfpgaimage.c
@@ -0,0 +1,365 @@ 
+/*
+ * Copyright (C) 2014 Charles Manning <cdhmanning@gmail.com>
+ *
+ * Use as you see fit.
+ *
+ * Reference doc http://www.altera.com.cn/literature/hb/cyclone-v/cv_5400A.pdf
+ * Note this doc is not entirely accurate.
+ *
+ * "Header" is a structure of the following format.
+ * this is positioned at 0x40.
+ *
+ * Endian is LSB.
+ *
+ * Offset   Length   Usage
+ * -----------------------
+ *   0x40        4   Validation word 0x31305341
+ *   0x44        1   Version (whatever, zero is fine)
+ *   0x45        1   Flags   (unused, zero is fine)
+ *   0x46        2   Length  (in units of u32, including the end checksum).
+ *   0x48        2   Zero
+ *   0x0A        2   Checksum over the heder. NB Not CRC32
+ *
+ * At the end of the code we have a 32-bit CRC checksum over whole binary
+ * excluding the CRC.
+ *
+ * The image is typically padded out to 64k, because that is what is used
+ * to write the image to the boot medium.
+ *
+ * This uses the CRC32 calc out of the well known Apple
+ * crc32.c code. CRC32 algorithms do not produce the same results.
+ * We need this one. Sorry about the coade bloat.
+ *
+ * Copyright for the CRC code:
+ *
+ * COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
+ *  code or tables extracted from it, as desired without restriction.
+ *
+ */
+
+#include "imagetool.h"
+#include <image.h>
+
+#define HEADER_OFFSET	0x40
+#define HEADER_SIZE	0x0C
+#define MAX_IMAGE_SIZE 0xFF00
+#define VALIDATION_WORD	0x31305341
+#define FILL_BYTE	0x00
+#define PADDED_SIZE	0x10000
+
+
+static uint8_t buffer[PADDED_SIZE];
+
+/*
+ * The header checksum is just a very simple checksum over
+ * the header area.
+ * There is still a crc32 over the whole lot.
+ */
+static uint16_t hdr_checksum(const uint8_t *buf, int len)
+{
+	uint16_t ret = 0;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		ret += (((uint16_t) *buf) & 0xff);
+		buf++;
+	}
+	return ret;
+}
+
+/*
+ * Some byte marshalling functions...
+ *
+ */
+
+static void load_le16(uint8_t *buf, uint16_t v)
+{
+	buf[0] = (v >> 0) & 0xff;
+	buf[1] = (v >> 8) & 0xff;
+}
+
+static void load_le32(uint8_t *buf, uint32_t v)
+{
+	buf[0] = (v >>  0) & 0xff;
+	buf[1] = (v >>  8) & 0xff;
+	buf[2] = (v >> 16) & 0xff;
+	buf[3] = (v >> 24) & 0xff;
+}
+
+static uint16_t get_le16(const uint8_t *buf)
+{
+	uint16_t retval;
+
+	retval = (((uint16_t) buf[0]) << 0) |
+		 (((uint16_t) buf[1]) << 8);
+	return retval;
+}
+
+static uint32_t get_le32(const uint8_t *buf)
+{
+	uint32_t retval;
+
+	retval = (((uint32_t) buf[0]) <<  0) |
+		 (((uint32_t) buf[1]) <<  8) |
+		 (((uint32_t) buf[2]) << 16) |
+		 (((uint32_t) buf[3]) << 24);
+	return retval;
+}
+
+static int align4(int v)
+{
+	return ((v + 3) / 4) * 4;
+}
+
+static void build_header(uint8_t *buf,
+			  uint8_t version,
+			  uint8_t flags,
+			  uint16_t length_bytes)
+{
+	memset(buf, 0, HEADER_SIZE);
+
+	load_le32(buf + 0, VALIDATION_WORD);
+	buf[4] = version;
+	buf[5] = flags;
+	load_le16(buf + 6, length_bytes/4);
+	load_le16(buf + 10, hdr_checksum(buf, 10));
+}
+
+/* Verify the header and return size of image */
+static int verify_header(const uint8_t *buf)
+{
+	if (get_le32(buf) != VALIDATION_WORD)
+		return -1;
+	if (get_le16(buf + 10) != hdr_checksum(buf, 10))
+		return -1;
+
+	return get_le16(buf+6) * 4;
+}
+
+/* Local CRC32 function. Lifted from Apple CRC32. */
+static uint32_t crc_table[256] = {
+	0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
+	0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
+	0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+	0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
+	0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+	0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
+	0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
+	0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
+	0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
+	0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+	0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
+	0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+	0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
+	0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
+	0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+	0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
+	0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+	0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
+	0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
+	0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
+	0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
+	0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+	0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
+	0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+	0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
+	0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
+	0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+	0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
+	0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+	0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
+	0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
+	0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
+	0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
+	0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+	0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
+	0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+	0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
+	0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
+	0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+	0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
+	0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+	0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
+	0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
+	0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
+	0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
+	0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+	0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
+	0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+	0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
+	0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
+	0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+	0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+static uint32_t local_crc32(uint32_t crc, const void *_buf, int length)
+{
+	const uint8_t *buf = _buf;
+
+	crc ^= ~0;
+
+	while (length--) {
+		crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *buf) & 0xff];
+		buf++;
+	}
+
+	crc ^= ~0;
+
+	return crc;
+}
+
+/* Sign the buffer and return the signed buffer size */
+static int sign_buffer(uint8_t *buf,
+			uint8_t version, uint8_t flags,
+			int len, int pad_64k)
+{
+	uint32_t crcval;
+
+	/* Align the length up */
+	len = align4(len);
+
+	/* Build header, adding 4 bytes to length to hold the CRC32. */
+	build_header(buf + HEADER_OFFSET,  version, flags, len + 4);
+
+	crcval = local_crc32(0, buf, len);
+
+	load_le32(buf + len, crcval);
+
+	if (!pad_64k)
+		return len + 4;
+
+	return PADDED_SIZE;
+}
+
+/* Verify that the buffer looks sane */
+static int verify_buffer(const uint8_t *buf)
+{
+	int len; /* Including 32bit CRC */
+	uint32_t crccalc;
+
+	len = verify_header(buf + HEADER_OFFSET);
+	if (len < 0)
+		return -1;
+	if (len < HEADER_OFFSET || len > PADDED_SIZE)
+		return -1;
+
+	/* Adjust length, removing CRC */
+	len -= 4;
+
+	crccalc = local_crc32(0, buf, len);
+
+	if (get_le32(buf + len) != crccalc)
+		return -1;
+
+	return 0;
+}
+
+/* mkimage glue functions */
+
+static int socfpgaimage_verify_header(unsigned char *ptr, int image_size,
+			struct image_tool_params *params)
+{
+	if (image_size != PADDED_SIZE)
+		return -1;
+
+	return verify_buffer(ptr);
+}
+
+static void socfpgaimage_print_header(const void *ptr)
+{
+	if (verify_buffer(ptr) == 0)
+		printf("Looks like a sane SOCFPGA preloader\n");
+	else
+		printf("Not a sane SOCFPGA preloader\n");
+}
+
+static int socfpgaimage_check_params(struct image_tool_params *params)
+{
+	/* Not sure if we should be accepting fflags */
+	return	(params->dflag && (params->fflag || params->lflag)) ||
+		(params->fflag && (params->dflag || params->lflag)) ||
+		(params->lflag && (params->dflag || params->fflag));
+}
+
+static int socfpgaimage_check_image_types(uint8_t type)
+{
+	if (type == IH_TYPE_SOCFPGAIMAGE)
+		return EXIT_SUCCESS;
+	else
+		return EXIT_FAILURE;
+}
+
+/* To work in with the mkimage framework, we do some ugly stuff...
+ *
+ * First we prepend a fake header big enough to make the file 64k.
+ * When set_header is called, we fix this up by moving the image
+ * around in the buffer.
+ */
+
+static int data_size;
+#define fake_header_size (PADDED_SIZE - data_size)
+
+/* Use vrec_header to set up the fake header */
+
+static int socfpgaimage_vrec_header(struct image_tool_params *params,
+				struct image_type_params *tparams)
+{
+	struct stat sbuf;
+
+	if (!params->datafile || stat(params->datafile, &sbuf) < 0)
+		return 0;
+
+	data_size = sbuf.st_size;
+	tparams->header_size = fake_header_size;
+
+	return 0;
+}
+
+static void socfpgaimage_set_header(void *ptr, struct stat *sbuf, int ifd,
+				struct image_tool_params *params)
+{
+	uint8_t *buf = (uint8_t *)ptr;
+
+	/* At this stage we have the header_size dummy bytes followed by
+	 * PADDED_SIZE-header_size image bytes.
+	 * We need to fix the buffer by moving the image bytes back to
+	 * the beginning of the buffer, then actually do the signing stuff...
+	 */
+	memmove(buf, buf + fake_header_size, data_size);
+	memset(buf + data_size, 0, fake_header_size);
+
+	sign_buffer(buf, 0, 0, data_size, 0);
+}
+
+/*
+ * socfpgaimage parameters
+ */
+static struct image_type_params socfpgaimage_params = {
+	.name		= "Altera SOCFPGA preloader support",
+	.vrec_header	= socfpgaimage_vrec_header,
+	.header_size	= 0,
+	.hdr		= (void *)buffer,
+	.check_image_type = socfpgaimage_check_image_types,
+	.verify_header	= socfpgaimage_verify_header,
+	.print_header	= socfpgaimage_print_header,
+	.set_header	= socfpgaimage_set_header,
+	.check_params	= socfpgaimage_check_params,
+};
+
+void init_socfpga_image_type(void)
+{
+	register_image_type(&socfpgaimage_params);
+}
+