162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * fs/partitions/atari.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Code extracted from drivers/block/genhd.c 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 1991-1998 Linus Torvalds 862306a36Sopenharmony_ci * Re-organised Feb 1998 Russell King 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/ctype.h> 1262306a36Sopenharmony_ci#include "check.h" 1362306a36Sopenharmony_ci#include "atari.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* ++guenther: this should be settable by the user ("make config")?. 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_ci#define ICD_PARTS 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* check if a partition entry looks valid -- Atari format is assumed if at 2062306a36Sopenharmony_ci least one of the primary entries is ok this way */ 2162306a36Sopenharmony_ci#define VALID_PARTITION(pi,hdsiz) \ 2262306a36Sopenharmony_ci (((pi)->flg & 1) && \ 2362306a36Sopenharmony_ci isalnum((pi)->id[0]) && isalnum((pi)->id[1]) && isalnum((pi)->id[2]) && \ 2462306a36Sopenharmony_ci be32_to_cpu((pi)->st) <= (hdsiz) && \ 2562306a36Sopenharmony_ci be32_to_cpu((pi)->st) + be32_to_cpu((pi)->siz) <= (hdsiz)) 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic inline int OK_id(char *s) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci return memcmp (s, "GEM", 3) == 0 || memcmp (s, "BGM", 3) == 0 || 3062306a36Sopenharmony_ci memcmp (s, "LNX", 3) == 0 || memcmp (s, "SWP", 3) == 0 || 3162306a36Sopenharmony_ci memcmp (s, "RAW", 3) == 0 ; 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ciint atari_partition(struct parsed_partitions *state) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci Sector sect; 3762306a36Sopenharmony_ci struct rootsector *rs; 3862306a36Sopenharmony_ci struct partition_info *pi; 3962306a36Sopenharmony_ci u32 extensect; 4062306a36Sopenharmony_ci u32 hd_size; 4162306a36Sopenharmony_ci int slot; 4262306a36Sopenharmony_ci#ifdef ICD_PARTS 4362306a36Sopenharmony_ci int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */ 4462306a36Sopenharmony_ci#endif 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci /* 4762306a36Sopenharmony_ci * ATARI partition scheme supports 512 lba only. If this is not 4862306a36Sopenharmony_ci * the case, bail early to avoid miscalculating hd_size. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_ci if (queue_logical_block_size(state->disk->queue) != 512) 5162306a36Sopenharmony_ci return 0; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci rs = read_part_sector(state, 0, §); 5462306a36Sopenharmony_ci if (!rs) 5562306a36Sopenharmony_ci return -1; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci /* Verify this is an Atari rootsector: */ 5862306a36Sopenharmony_ci hd_size = get_capacity(state->disk); 5962306a36Sopenharmony_ci if (!VALID_PARTITION(&rs->part[0], hd_size) && 6062306a36Sopenharmony_ci !VALID_PARTITION(&rs->part[1], hd_size) && 6162306a36Sopenharmony_ci !VALID_PARTITION(&rs->part[2], hd_size) && 6262306a36Sopenharmony_ci !VALID_PARTITION(&rs->part[3], hd_size)) { 6362306a36Sopenharmony_ci /* 6462306a36Sopenharmony_ci * if there's no valid primary partition, assume that no Atari 6562306a36Sopenharmony_ci * format partition table (there's no reliable magic or the like 6662306a36Sopenharmony_ci * :-() 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_ci put_dev_sector(sect); 6962306a36Sopenharmony_ci return 0; 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci pi = &rs->part[0]; 7362306a36Sopenharmony_ci strlcat(state->pp_buf, " AHDI", PAGE_SIZE); 7462306a36Sopenharmony_ci for (slot = 1; pi < &rs->part[4] && slot < state->limit; slot++, pi++) { 7562306a36Sopenharmony_ci struct rootsector *xrs; 7662306a36Sopenharmony_ci Sector sect2; 7762306a36Sopenharmony_ci ulong partsect; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if ( !(pi->flg & 1) ) 8062306a36Sopenharmony_ci continue; 8162306a36Sopenharmony_ci /* active partition */ 8262306a36Sopenharmony_ci if (memcmp (pi->id, "XGM", 3) != 0) { 8362306a36Sopenharmony_ci /* we don't care about other id's */ 8462306a36Sopenharmony_ci put_partition (state, slot, be32_to_cpu(pi->st), 8562306a36Sopenharmony_ci be32_to_cpu(pi->siz)); 8662306a36Sopenharmony_ci continue; 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci /* extension partition */ 8962306a36Sopenharmony_ci#ifdef ICD_PARTS 9062306a36Sopenharmony_ci part_fmt = 1; 9162306a36Sopenharmony_ci#endif 9262306a36Sopenharmony_ci strlcat(state->pp_buf, " XGM<", PAGE_SIZE); 9362306a36Sopenharmony_ci partsect = extensect = be32_to_cpu(pi->st); 9462306a36Sopenharmony_ci while (1) { 9562306a36Sopenharmony_ci xrs = read_part_sector(state, partsect, §2); 9662306a36Sopenharmony_ci if (!xrs) { 9762306a36Sopenharmony_ci printk (" block %ld read failed\n", partsect); 9862306a36Sopenharmony_ci put_dev_sector(sect); 9962306a36Sopenharmony_ci return -1; 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci /* ++roman: sanity check: bit 0 of flg field must be set */ 10362306a36Sopenharmony_ci if (!(xrs->part[0].flg & 1)) { 10462306a36Sopenharmony_ci printk( "\nFirst sub-partition in extended partition is not valid!\n" ); 10562306a36Sopenharmony_ci put_dev_sector(sect2); 10662306a36Sopenharmony_ci break; 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci put_partition(state, slot, 11062306a36Sopenharmony_ci partsect + be32_to_cpu(xrs->part[0].st), 11162306a36Sopenharmony_ci be32_to_cpu(xrs->part[0].siz)); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci if (!(xrs->part[1].flg & 1)) { 11462306a36Sopenharmony_ci /* end of linked partition list */ 11562306a36Sopenharmony_ci put_dev_sector(sect2); 11662306a36Sopenharmony_ci break; 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) { 11962306a36Sopenharmony_ci printk("\nID of extended partition is not XGM!\n"); 12062306a36Sopenharmony_ci put_dev_sector(sect2); 12162306a36Sopenharmony_ci break; 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci partsect = be32_to_cpu(xrs->part[1].st) + extensect; 12562306a36Sopenharmony_ci put_dev_sector(sect2); 12662306a36Sopenharmony_ci if (++slot == state->limit) { 12762306a36Sopenharmony_ci printk( "\nMaximum number of partitions reached!\n" ); 12862306a36Sopenharmony_ci break; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci strlcat(state->pp_buf, " >", PAGE_SIZE); 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci#ifdef ICD_PARTS 13462306a36Sopenharmony_ci if ( part_fmt!=1 ) { /* no extended partitions -> test ICD-format */ 13562306a36Sopenharmony_ci pi = &rs->icdpart[0]; 13662306a36Sopenharmony_ci /* sanity check: no ICD format if first partition invalid */ 13762306a36Sopenharmony_ci if (OK_id(pi->id)) { 13862306a36Sopenharmony_ci strlcat(state->pp_buf, " ICD<", PAGE_SIZE); 13962306a36Sopenharmony_ci for (; pi < &rs->icdpart[8] && slot < state->limit; slot++, pi++) { 14062306a36Sopenharmony_ci /* accept only GEM,BGM,RAW,LNX,SWP partitions */ 14162306a36Sopenharmony_ci if (!((pi->flg & 1) && OK_id(pi->id))) 14262306a36Sopenharmony_ci continue; 14362306a36Sopenharmony_ci put_partition (state, slot, 14462306a36Sopenharmony_ci be32_to_cpu(pi->st), 14562306a36Sopenharmony_ci be32_to_cpu(pi->siz)); 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci strlcat(state->pp_buf, " >", PAGE_SIZE); 14862306a36Sopenharmony_ci } 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci#endif 15162306a36Sopenharmony_ci put_dev_sector(sect); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci strlcat(state->pp_buf, "\n", PAGE_SIZE); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci return 1; 15662306a36Sopenharmony_ci} 157