/* * bootpage.c is a modified version of: * $Id: tpip.c,v 1.19 2004/01/12 03:12:34 millert Exp $ * * Copyright (c) 2003-2004 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #if BYTE_ORDER == BIG_ENDIAN # define TIVO_BOOT_MAGIC 0x1492 # define MAC_PARTITION_MAGIC 0x504d #elif BYTE_ORDER == LITTLE_ENDIAN # define TIVO_BOOT_MAGIC 0x9214 # define MAC_PARTITION_MAGIC 0x4d50 #else # error Unknown byte order! #endif #define HOST_BYTE_ORDER BYTE_ORDER struct tcdbootpage { /* * NOTE: values are stored in network byte order (little endian) */ u_int16_t signature; u_int8_t primaryBootPartition; u_int8_t alternateBootPartition; char bootParams[128]; char padding[380]; /* we don't need the other bits */ }; int TIVO_BYTE_ORDER; char *bootpage(const char *device) { int fd; struct tcdbootpage *bootpg, bpbuf[2]; if ((fd = open(device, O_RDWR, 0644)) == -1) err(1, "error opening %s", device); /* read the TiVo boot page */ bootpg = &bpbuf[0]; switch (read(fd, bootpg, sizeof(struct tcdbootpage))) { case -1: fprintf(stderr, "error reading from %s", device); return NULL; case sizeof(struct tcdbootpage): /* OK */ break; default: fprintf(stderr, "%s: short read", device); return NULL; } if (bootpg->signature == TIVO_BOOT_MAGIC) { TIVO_BYTE_ORDER = HOST_BYTE_ORDER; } else if (bootpg->signature == cpu_to_be16(TIVO_BOOT_MAGIC)) { // TiVo disk is byte-swapped #if HOST_BYTE_ORDER == BIG_ENDIAN TIVO_BYTE_ORDER = LITTLE_ENDIAN; #else TIVO_BYTE_ORDER = BIG_ENDIAN; #endif swab((char *)&bpbuf[0], (char *)&bpbuf[1], sizeof(struct tcdbootpage)); bootpg = &bpbuf[1]; } else if (bootpg->signature != TIVO_BOOT_MAGIC) { fprintf(stderr, "unknown bootpage signature: 0x%x", bootpg->signature); return NULL; } fsync(fd); return bootpg->bootParams; }