[RAZR i Q&A, Help & Troubleshooting] mattlgroff:
I think our best bet right now is to hope Motorola can give us documentation on this when the new MotoDev.com comes on November 1st. No device has really been in this position before, so the current tools and documentation aren't helpful. I appreciate you taking a look.

---------- Post added at 03:28 PM ---------- Previous post was at 03:19 PM ----------

Found this in the sourceforge under system_core.tar.gz:

Maybe helpful...maybe not. The tools could be in the sourceforge.

Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := mkbootimg.c
LOCAL_STATIC_LIBRARIES := libmincrypt

LOCAL_MODULE := mkbootimg

include $(BUILD_HOST_EXECUTABLE)

$(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE))

mkbootimg.c

/* tools/mkbootimg/mkbootimg.c
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#include "mincrypt/sha.h"
#include "bootimg.h"

static void *load_file(const char *fn, unsigned *_sz)
{
char *data;
int sz;
int fd;

data = 0;
fd = open(fn, O_RDONLY);
if(fd < 0) return 0;

sz = lseek(fd, 0, SEEK_END);
if(sz < 0) goto oops;

if(lseek(fd, 0, SEEK_SET) != 0) goto oops;

data = (char*) malloc(sz);
if(data == 0) goto oops;

if(read(fd, data, sz) != sz) goto oops;
close(fd);

if(_sz) *_sz = sz;
return data;

oops:
close(fd);
if(data != 0) free(data);
return 0;
}

int usage(void)
{
fprintf(stderr,"usage: mkbootimg\n"
" --kernel <filename>\n"
" --ramdisk <filename>\n"
" [ --second <2ndbootloader-filename> ]\n"
" [ --cmdline <kernel-commandline> ]\n"
" [ --board <boardname> ]\n"
" [ --base <address> ]\n"
" [ --pagesize <pagesize> ]\n"
" -o|--output <filename>\n"
);
return 1;
}

static unsigned char padding[4096] = { 0, };

int write_padding(int fd, unsigned pagesize, unsigned itemsize)
{
unsigned pagemask = pagesize - 1;
unsigned count;

if((itemsize & pagemask) == 0) {
return 0;
}

count = pagesize - (itemsize & pagemask);

if(write(fd, padding, count) != count) {
return -1;
} else {
return 0;
}
}

int main(int argc, char **argv)
{
boot_img_hdr hdr;

char *kernel_fn = 0;
void *kernel_data = 0;
char *ramdisk_fn = 0;
void *ramdisk_data = 0;
char *second_fn = 0;
void *second_data = 0;
char *cmdline = "";
char *bootimg = 0;
char *board = "";
unsigned pagesize = 2048;
int fd;
SHA_CTX ctx;
uint8_t* sha;

argc--;
argv++;

memset(&hdr, 0, sizeof(hdr));

/* default load addresses */
hdr.kernel_addr = 0x10008000;
hdr.ramdisk_addr = 0x11000000;
hdr.second_addr = 0x10F00000;
hdr.tags_addr = 0x10000100;

while(argc > 0){
char *arg = argv[0];
char *val = argv[1];
if(argc < 2) {
return usage();
}
argc -= 2;
argv += 2;
if(!strcmp(arg, "--output") || !strcmp(arg, "-o")) {
bootimg = val;
} else if(!strcmp(arg, "--kernel")) {
kernel_fn = val;
} else if(!strcmp(arg, "--ramdisk")) {
ramdisk_fn = val;
} else if(!strcmp(arg, "--second")) {
second_fn = val;
} else if(!strcmp(arg, "--cmdline")) {
cmdline = val;
} else if(!strcmp(arg, "--base")) {
unsigned base = strtoul(val, 0, 16);
hdr.kernel_addr = base + 0x00008000;
hdr.ramdisk_addr = base + 0x01000000;
hdr.second_addr = base + 0x00F00000;
hdr.tags_addr = base + 0x00000100;
} else if(!strcmp(arg, "--board")) {
board = val;
} else if(!strcmp(arg,"--pagesize")) {
pagesize = strtoul(val, 0, 10);
if ((pagesize != 2048) && (pagesize != 4096)) {
fprintf(stderr,"error: unsupported page size %d\n", pagesize);
return -1;
}
} else {
return usage();
}
}
hdr.page_size = pagesize;

if(bootimg == 0) {
fprintf(stderr,"error: no output filename specified\n");
return usage();
}

if(kernel_fn == 0) {
fprintf(stderr,"error: no kernel image specified\n");
return usage();
}

if(ramdisk_fn == 0) {
fprintf(stderr,"error: no ramdisk image specified\n");
return usage();
}

if(strlen(board) >= BOOT_NAME_SIZE) {
fprintf(stderr,"error: board name too large\n");
return usage();
}

strcpy(hdr.name, board);

memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);

if(strlen(cmdline) > (BOOT_ARGS_SIZE - 1)) {
fprintf(stderr,"error: kernel commandline too large\n");
return 1;
}
strcpy((char*)hdr.cmdline, cmdline);

kernel_data = load_file(kernel_fn, &hdr.kernel_size);
if(kernel_data == 0) {
fprintf(stderr,"error: could not load kernel '%s'\n", kernel_fn);
return 1;
}

if(!strcmp(ramdisk_fn,"NONE")) {
ramdisk_data = 0;
hdr.ramdisk_size = 0;
} else {
ramdisk_data = load_file(ramdisk_fn, &hdr.ramdisk_size);
if(ramdisk_data == 0) {
fprintf(stderr,"error: could not load ramdisk '%s'\n", ramdisk_fn);
return 1;
}
}

if(second_fn) {
second_data = load_file(second_fn, &hdr.second_size);
if(second_data == 0) {
fprintf(stderr,"error: could not load secondstage '%s'\n", second_fn);
return 1;
}
}

/* put a hash of the contents in the header so boot images can be
* differentiated based on their first 2k.
*/
SHA_init(&ctx);
SHA_update(&ctx, kernel_data, hdr.kernel_size);
SHA_update(&ctx, &hdr.kernel_size, sizeof(hdr.kernel_size));
SHA_update(&ctx, ramdisk_data, hdr.ramdisk_size);
SHA_update(&ctx, &hdr.ramdisk_size, sizeof(hdr.ramdisk_size));
SHA_update(&ctx, second_data, hdr.second_size);
SHA_update(&ctx, &hdr.second_size, sizeof(hdr.second_size));
sha = SHA_final(&ctx);
memcpy(hdr.id, sha,
SHA_DIGEST_SIZE > sizeof(hdr.id) ? sizeof(hdr.id) : SHA_DIGEST_SIZE);

fd = open(bootimg, O_CREAT | O_TRUNC | O_WRONLY, 0644);
if(fd < 0) {
fprintf(stderr,"error: could not create '%s'\n", bootimg);
return 1;
}

if(write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) goto fail;
if(write_padding(fd, pagesize, sizeof(hdr))) goto fail;

if(write(fd, kernel_data, hdr.kernel_size) != hdr.kernel_size) goto fail;
if(write_padding(fd, pagesize, hdr.kernel_size)) goto fail;

if(write(fd, ramdisk_data, hdr.ramdisk_size) != hdr.ramdisk_size) goto fail;
if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;

if(second_data) {
if(write(fd, second_data, hdr.second_size) != hdr.second_size) goto fail;
if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
}

return 0;

fail:
unlink(bootimg);
close(fd);
fprintf(stderr,"error: failed writing '%s': %s\n", bootimg,
strerror(errno));
return 1;
}

bootimg.h

/* tools/mkbootimg/bootimg.h
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#ifndef _BOOT_IMAGE_H_
#define _BOOT_IMAGE_H_

typedef struct boot_img_hdr boot_img_hdr;

#define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512

struct boot_img_hdr
{
unsigned char magic[BOOT_MAGIC_SIZE];

unsigned kernel_size; /* size in bytes */
unsigned kernel_addr; /* physical load addr */

unsigned ramdisk_size; /* size in bytes */
unsigned ramdisk_addr; /* physical load addr */

unsigned second_size; /* size in bytes */
unsigned second_addr; /* physical load addr */

unsigned tags_addr; /* physical addr for kernel tags */
unsigned page_size; /* flash page size we assume */
unsigned unused[2]; /* future expansion: should be 0 */

unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */

unsigned char cmdline[BOOT_ARGS_SIZE];

unsigned id[8]; /* timestamp / checksum / sha1 / etc */
};

/*
** +-----------------+
** | boot header | 1 page
** +-----------------+
** | kernel | n pages
** +-----------------+
** | ramdisk | m pages
** +-----------------+
** | second stage | o pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
**
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
** 2. second is optional (second_size == 0 -> no second)
** 3. load each element (kernel, ramdisk, second) at
** the specified physical address (kernel_addr, etc)
** 4. prepare tags at tag_addr. kernel_args[] is
** appended to the kernel commandline in the tags.
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
** 6. if second_size != 0: jump to second_addr
** else: jump to kernel_addr
*/

#if 0
typedef struct ptentry ptentry;

struct ptentry {
char name[16]; /* asciiz partition name */
unsigned start; /* starting block number */
unsigned length; /* length in blocks */
unsigned flags; /* set to zero */
};

/* MSM Partition Table ATAG
**
** length: 2 + 7 * n
** atag: 0x4d534d70
** <ptentry> x n
*/
#endif

#endif

http://www.sourceforge.net/motorola/razr-i/