Subject: binary into AIF

From: thomas olausson <[email-masked]>
Date: Mon, 16 Aug 1999 18:14:40 -0400

The problem I have with the SA-1100 evaluation board
is that the boot loader expects gzipped AIF kernels.

Gzip is easy, but how do I make binaries into AIF?

Thomas
unsubscribe: body of `unsubscribe linux-arm' to [email-masked]

---

From: James Smith <[email-masked]>
Date: Fri, 20 Aug 1999 15:24:31 -0700

> Date: Mon, 16 Aug 1999 18:14:40 -0400
> From: thomas olausson <[email-masked]>

Well...

Create a data section that looks like an AIF header and ensure that
your linker script places that section at the start of the image. You
can then get your linker to output as a "raw" binary.

e.g.

Assemble this so that you have an object with a section
called "AIF_HDR":

	/*> aifhdr.S <*/
	/*---------------------------------------------------------------------------*/
	/* ARM executable image header support
	 *
	 * $Revision: 1.7 $
	 *   $Author: jamie $
	 *     $Date: 1999/05/29 10:28:36 $
	 *
         */
	/*---------------------------------------------------------------------------*/

		.equ    OS_Exit,0x11

		.section AIF_HDR /* readonly code */

		.globl  __start
	__start:
		/* The position of these initial fields is fixed by the AIF
		 * format, since external tools (e.g. armsd) expect a
		 * particular format. Also (for some strange reason regardless
		 * of whether the first two instructions have REAL
	         * branches... armsd ignores them and sets the starting PC to
	         * (base + 8).
		 */
		NOP			/* 0x00 compress_br */
		NOP			/* 0x04 reloc_br */
		BL      zinit		/* 0x08 zinit_br */
	__appstart:
		BL      __main		/* 0x0C standard entry point */
		/* At the moment our "__main" ignores passed arguments */
		SWI     OS_Exit		/* 0x10 exit SWI in case of return from entry_br */
		/* NOTE: GAS cannot cope with generating a relocation between
	         * two external symbols, so we have to have the link script
	         * create dummy symbols of the values we want:
	         */
	localrosize:
		.word   __ro_size__     /* 0x14 RO size */
		.word   __rw_size__     /* 0x18 RW size */
		.word   0x00000000      /* 0x1C dbg size */
		.word   __bss_size__    /* 0x20 BSS size */
		.word   0x00000000      /* 0x24 dbgtype (0,1,2 or 3) */
		.word   __start		/* 0x28 Image base */
	        .word   0x00000000	/* 0x2C workspace (link -rel -w only) */
		.word   32		/* 0x30 address mode (26/32) */
		.word   __rw_base__	/* 0x34 data base (address where image data linked) */
		.word	0x00000000      /* 0x38 reserved (used for FAT AIF images) */
		.word   0x00000000      /* 0x3C reserved */
		NOP			/* 0x40 debug initialisation SWI */
		/* The above NOP was referenced by ARM Ltd "zinit" calls, and
		 * the offset was explicitly "poked" with a SWI (or BL) to the
		 * run-time debug initialisation code when certain types of debug
	   	 * images were generated. To stay conforming (for at least the
		 * initial header) to the ARM Ltd specification, we leave
	         * this NOP available at 0x40.
		 *
		 * For the GCC builds we can now do whatever we want in the
		 * remainder of this initial section.
		 */
		/* We no longer need to conform to the ARM Ltd AIF header
		 * specification for size. We can add any new descriptor
		 * fields we require here. It also means that we can do
		 * symbolic operations within this section which we couldn't
		 * when using the ARM Ltd linker.
		 */
		/*-------------------------------------------------------------------*/

	zinit:	/* BSS initialisation code: */
	#if !defined(ORIG_AIF_CODE)
		... whatever you want here ...
	#else /* ORIG_AIF_CODE (kept for reference and for ZIP loader) */
		SUB     ip,lr,pc        /* base+12+[PSR]-(ZeroInit+12+[PSR]) */
	                                /* = base-ZeroInit */
		ADD     ip,pc,ip        /* base-ZeroInit+ZeroInit+16 = base+16 */
		LDMIB   ip,{r0,r1,r2,r3}/* various size information */
		SUB     ip,ip,#16       /* image base */
		LDR     r2,[ip,#48]     /* flags */
		TST     r2,#256         /* separate data area? */
		LDRNE   ip,[ip,#52]     /* Yes, so get it... */
		ADDEQ   ip,ip,r0        /* No, so add + RO size */
		ADD     ip,ip,r1        /* + RW size = base of 0-init area */
		MOV     r0,#0
		CMPS    r3,#0
	cl00:	MOVLE   pc,lr		/* nothing left to do */
		STR     r0,[ip],#4
		SUBS    r3,r3,#4
		B       cl00
	#endif /* ORIG_AIF_CODE */
	hdrend:

	/*---------------------------------------------------------------------------*/

		/* NOTE: The ARM Ltd linker would only allow AIF header
		 * replacement if the section was *EXACTLY* 0x80 bytes
		 * long. This is not a requirement for our GCC only build
		 * world.
		 */

	/*---------------------------------------------------------------------------*/
	/*> EOF aifhdr.S <*/

You can then have something like the following in your linker script:

	/* Currently we create AIF images. This is because the AIF header is
	 * used to hold special target descriptor flags. Also the current
	 * bootstrap and download code explicitly checks for an AIF style
	 * header. To enable an AIF image to be generated we force our
	 * special AIF header section to be the first in the produced
	 * application (see AIF_HDR below).
	 */

	GROUP(-lc)
	ENTRY(__start)

	SECTIONS
	{
		.text 0x00008000 : {
			__ro_base__ = .;
			/* Explicit image header: */
			*(AIF_HDR)

			/* Normal application code: */
			*(.text)
			/* Read-only data: */
			*(.rdata)
			. = ALIGN(0x4);
			___CTOR_LIST__ = .;
			__CTOR_LIST__ = .; 
				LONG (-1);
				*(.ctors);
				*(.ctor);
				LONG (0); 
			___DTOR_LIST__ = .;
			__DTOR_LIST__ = . ; 
	                        LONG (-1);
				*(.dtors);
				*(.dtor);
				LONG (0); 

			*(.fini)
			. = ALIGN(0x4);
			__ro_limit__ = .;
		}

		/* Initialised data. Logically placed at a higher address, but
		   we use AT to ensure that the image file produced contains
		   the loadable data immediately after the .text section: */
		.data 0x60000000 : AT (__ro_limit__) {
			__rw_base__ = .;
			__data_start__ = .;
			*(.rwcode)
			*(.data)
			. = ALIGN(0x4);
			__data_end__ = .;
			edata = .;
		}
		.bss (__data_end__) (NOLOAD) : {
			__bss_start__ = .;
			__bss_base__ = .;
			*(.bss)
			*(COMMON)
			. = ALIGN(0x4);
			__bss_limit__ = .;
			__bss_end__ = .;
		}
		__rw_limit__ = .;
		__ro_size__ = (__ro_limit__ - __ro_base__);
		__rw_size__ = (__bss_start__ - __rw_base__);
		__bss_size__ = (__bss_end__ - __bss_start__);
		__end__ = .;
	}

You can then link with something like the following (if the above
script is in "linkmap.ld", and the AIF header source assembled into
the file "aifhdr.o"):

	ld --strip-all --oformat binary -T linkmap.ld -o <target> aifhdr.o <other objs and other bits>

Hope the above helps :-)

(NOTE: I have not played with the SA1100 kernel bootstrapping... the
above is how I used to use GNU generated images for downloading to an
"old ARM-Demon" based board using armsd). GDB was still used for
high-level debugging to the Demon based board (since it understands
RDP), but having the AIF header allows for "armsd" to be used for
low-level (i.e. non-symbolic) debugging).

-- Jamie