/*
* atari.c
* Detection of ATARI ST partition map
*
* Copyright (c) 2003 Christoph Pfisterer
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "global.h"
/*
* ATARI ST partition map
*/
static char * get_name_for_type(char *type)
{
if (memcmp(type, "GEM", 3) == 0)
return "Standard GEMDOS";
else if (memcmp(type, "BGM", 3) == 0)
return "Big GEMDOS";
else if (memcmp(type, "XGM", 3) == 0)
return "Extended";
return "Unknown";
}
static void detect_atari_partmap_ext(SECTION *section, u8 extbase, int level);
void detect_atari_partmap(SECTION *section, int level)
{
unsigned char *buf;
int i, off, used, flag, flags[4];
u4 start, size, starts[4], sizes[4];
char types[4][4], *type;
u2 atari_csum;
char s[256], append[64];
/* partition maps only occur at the start of a device */
if (section->pos != 0)
return;
if (get_buffer(section, 0, 512, (void **)&buf) < 512)
return;
/* check checksum */
atari_csum = 0;
for (i = 0; i < 512; i += 2)
atari_csum += get_be_short(buf + i);
if (atari_csum != 0x1234)
return;
/* get data and check if it's actually used */
used = 0;
for (off = 0x1c6, i = 0; i < 4; i++, off += 12) {
flags[i] = buf[off];
get_string(buf + off + 1, 3, types[i]);
starts[i] = get_be_long(buf + off + 4);
sizes[i] = get_be_long(buf + off + 8);
if ((flags[i] & 1) && starts[i] != 0 && sizes[i] != 0)
used = 1;
}
if (!used)
return;
/* print data and handle each partition */
print_line(level, "ATARI ST partition map");
for (i = 0; i < 4; i++) {
start = starts[i];
size = sizes[i];
flag = flags[i];
type = types[i];
if ((flag & 1) == 0)
continue;
sprintf(append, " from %lu", start);
if (flag & 0x80)
strcat(append, ", bootable");
format_blocky_size(s, size, 512, "sectors", append);
print_line(level, "Partition %d: %s",
i+1, s);
print_line(level + 1, "Type \"%s\" (%s)", type,
get_name_for_type(type));
if (memcmp(type, "XGM", 3) == 0) {
/* extended partition */
detect_atari_partmap_ext(section, start, level + 1);
} else {
/* recurse for content detection */
analyze_recursive(section, level + 1,
(u8)start * 512, (u8)size * 512, 0);
}
}
}
static void detect_atari_partmap_ext(SECTION *section, u8 extbase, int level)
{
unsigned char *buf;
int extpartnum = 5;
u8 tablebase, nexttablebase;
int i, off, flags[4];
u4 start, size, starts[4], sizes[4];
char types[4][4], *type;
char s[256], append[64];
for (tablebase = extbase; tablebase; tablebase = nexttablebase) {
/* read sector from linked list */
if (get_buffer(section, tablebase << 9, 512, (void **)&buf) < 512)
return;
/* get data */
for (off = 0x1c6, i = 0; i < 4; i++, off += 12) {
flags[i] = buf[off];
get_string(buf + off + 1, 3, types[i]);
starts[i] = get_be_long(buf + off + 4);
sizes[i] = get_be_long(buf + off + 8);
}
/* print data and handle each partition */
nexttablebase = 0;
for (i = 0; i < 4; i++) {
start = starts[i];
size = sizes[i];
type = types[i];
if ((flags[i] & 1) == 0)
continue;
if (memcmp(type, "XGM", 3) == 0) {
/* link to next table */
nexttablebase = extbase + start;
} else {
/* real partition */
sprintf(append, " from %lu", start);
format_blocky_size(s, size, 512, "sectors", append);
print_line(level, "Partition %d: %s",
extpartnum, s);
extpartnum++;
print_line(level + 1, "Type \"%s\" (%s)", type,
get_name_for_type(type));
/* recurse for content detection */
analyze_recursive(section, level + 1,
(tablebase + start) * 512, (u8)size * 512, 0);
}
}
}
}
/* EOF */
syntax highlighted by Code2HTML, v. 0.9.1