18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * fs/partitions/atari.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Code extracted from drivers/block/genhd.c 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 1991-1998 Linus Torvalds 88c2ecf20Sopenharmony_ci * Re-organised Feb 1998 Russell King 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/ctype.h> 128c2ecf20Sopenharmony_ci#include "check.h" 138c2ecf20Sopenharmony_ci#include "atari.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci/* ++guenther: this should be settable by the user ("make config")?. 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_ci#define ICD_PARTS 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* check if a partition entry looks valid -- Atari format is assumed if at 208c2ecf20Sopenharmony_ci least one of the primary entries is ok this way */ 218c2ecf20Sopenharmony_ci#define VALID_PARTITION(pi,hdsiz) \ 228c2ecf20Sopenharmony_ci (((pi)->flg & 1) && \ 238c2ecf20Sopenharmony_ci isalnum((pi)->id[0]) && isalnum((pi)->id[1]) && isalnum((pi)->id[2]) && \ 248c2ecf20Sopenharmony_ci be32_to_cpu((pi)->st) <= (hdsiz) && \ 258c2ecf20Sopenharmony_ci be32_to_cpu((pi)->st) + be32_to_cpu((pi)->siz) <= (hdsiz)) 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic inline int OK_id(char *s) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci return memcmp (s, "GEM", 3) == 0 || memcmp (s, "BGM", 3) == 0 || 308c2ecf20Sopenharmony_ci memcmp (s, "LNX", 3) == 0 || memcmp (s, "SWP", 3) == 0 || 318c2ecf20Sopenharmony_ci memcmp (s, "RAW", 3) == 0 ; 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ciint atari_partition(struct parsed_partitions *state) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci Sector sect; 378c2ecf20Sopenharmony_ci struct rootsector *rs; 388c2ecf20Sopenharmony_ci struct partition_info *pi; 398c2ecf20Sopenharmony_ci u32 extensect; 408c2ecf20Sopenharmony_ci u32 hd_size; 418c2ecf20Sopenharmony_ci int slot; 428c2ecf20Sopenharmony_ci#ifdef ICD_PARTS 438c2ecf20Sopenharmony_ci int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */ 448c2ecf20Sopenharmony_ci#endif 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci /* 478c2ecf20Sopenharmony_ci * ATARI partition scheme supports 512 lba only. If this is not 488c2ecf20Sopenharmony_ci * the case, bail early to avoid miscalculating hd_size. 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_ci if (bdev_logical_block_size(state->bdev) != 512) 518c2ecf20Sopenharmony_ci return 0; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci rs = read_part_sector(state, 0, §); 548c2ecf20Sopenharmony_ci if (!rs) 558c2ecf20Sopenharmony_ci return -1; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci /* Verify this is an Atari rootsector: */ 588c2ecf20Sopenharmony_ci hd_size = state->bdev->bd_inode->i_size >> 9; 598c2ecf20Sopenharmony_ci if (!VALID_PARTITION(&rs->part[0], hd_size) && 608c2ecf20Sopenharmony_ci !VALID_PARTITION(&rs->part[1], hd_size) && 618c2ecf20Sopenharmony_ci !VALID_PARTITION(&rs->part[2], hd_size) && 628c2ecf20Sopenharmony_ci !VALID_PARTITION(&rs->part[3], hd_size)) { 638c2ecf20Sopenharmony_ci /* 648c2ecf20Sopenharmony_ci * if there's no valid primary partition, assume that no Atari 658c2ecf20Sopenharmony_ci * format partition table (there's no reliable magic or the like 668c2ecf20Sopenharmony_ci * :-() 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_ci put_dev_sector(sect); 698c2ecf20Sopenharmony_ci return 0; 708c2ecf20Sopenharmony_ci } 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci pi = &rs->part[0]; 738c2ecf20Sopenharmony_ci strlcat(state->pp_buf, " AHDI", PAGE_SIZE); 748c2ecf20Sopenharmony_ci for (slot = 1; pi < &rs->part[4] && slot < state->limit; slot++, pi++) { 758c2ecf20Sopenharmony_ci struct rootsector *xrs; 768c2ecf20Sopenharmony_ci Sector sect2; 778c2ecf20Sopenharmony_ci ulong partsect; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if ( !(pi->flg & 1) ) 808c2ecf20Sopenharmony_ci continue; 818c2ecf20Sopenharmony_ci /* active partition */ 828c2ecf20Sopenharmony_ci if (memcmp (pi->id, "XGM", 3) != 0) { 838c2ecf20Sopenharmony_ci /* we don't care about other id's */ 848c2ecf20Sopenharmony_ci put_partition (state, slot, be32_to_cpu(pi->st), 858c2ecf20Sopenharmony_ci be32_to_cpu(pi->siz)); 868c2ecf20Sopenharmony_ci continue; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci /* extension partition */ 898c2ecf20Sopenharmony_ci#ifdef ICD_PARTS 908c2ecf20Sopenharmony_ci part_fmt = 1; 918c2ecf20Sopenharmony_ci#endif 928c2ecf20Sopenharmony_ci strlcat(state->pp_buf, " XGM<", PAGE_SIZE); 938c2ecf20Sopenharmony_ci partsect = extensect = be32_to_cpu(pi->st); 948c2ecf20Sopenharmony_ci while (1) { 958c2ecf20Sopenharmony_ci xrs = read_part_sector(state, partsect, §2); 968c2ecf20Sopenharmony_ci if (!xrs) { 978c2ecf20Sopenharmony_ci printk (" block %ld read failed\n", partsect); 988c2ecf20Sopenharmony_ci put_dev_sector(sect); 998c2ecf20Sopenharmony_ci return -1; 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci /* ++roman: sanity check: bit 0 of flg field must be set */ 1038c2ecf20Sopenharmony_ci if (!(xrs->part[0].flg & 1)) { 1048c2ecf20Sopenharmony_ci printk( "\nFirst sub-partition in extended partition is not valid!\n" ); 1058c2ecf20Sopenharmony_ci put_dev_sector(sect2); 1068c2ecf20Sopenharmony_ci break; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci put_partition(state, slot, 1108c2ecf20Sopenharmony_ci partsect + be32_to_cpu(xrs->part[0].st), 1118c2ecf20Sopenharmony_ci be32_to_cpu(xrs->part[0].siz)); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci if (!(xrs->part[1].flg & 1)) { 1148c2ecf20Sopenharmony_ci /* end of linked partition list */ 1158c2ecf20Sopenharmony_ci put_dev_sector(sect2); 1168c2ecf20Sopenharmony_ci break; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) { 1198c2ecf20Sopenharmony_ci printk("\nID of extended partition is not XGM!\n"); 1208c2ecf20Sopenharmony_ci put_dev_sector(sect2); 1218c2ecf20Sopenharmony_ci break; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci partsect = be32_to_cpu(xrs->part[1].st) + extensect; 1258c2ecf20Sopenharmony_ci put_dev_sector(sect2); 1268c2ecf20Sopenharmony_ci if (++slot == state->limit) { 1278c2ecf20Sopenharmony_ci printk( "\nMaximum number of partitions reached!\n" ); 1288c2ecf20Sopenharmony_ci break; 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci strlcat(state->pp_buf, " >", PAGE_SIZE); 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci#ifdef ICD_PARTS 1348c2ecf20Sopenharmony_ci if ( part_fmt!=1 ) { /* no extended partitions -> test ICD-format */ 1358c2ecf20Sopenharmony_ci pi = &rs->icdpart[0]; 1368c2ecf20Sopenharmony_ci /* sanity check: no ICD format if first partition invalid */ 1378c2ecf20Sopenharmony_ci if (OK_id(pi->id)) { 1388c2ecf20Sopenharmony_ci strlcat(state->pp_buf, " ICD<", PAGE_SIZE); 1398c2ecf20Sopenharmony_ci for (; pi < &rs->icdpart[8] && slot < state->limit; slot++, pi++) { 1408c2ecf20Sopenharmony_ci /* accept only GEM,BGM,RAW,LNX,SWP partitions */ 1418c2ecf20Sopenharmony_ci if (!((pi->flg & 1) && OK_id(pi->id))) 1428c2ecf20Sopenharmony_ci continue; 1438c2ecf20Sopenharmony_ci part_fmt = 2; 1448c2ecf20Sopenharmony_ci put_partition (state, slot, 1458c2ecf20Sopenharmony_ci be32_to_cpu(pi->st), 1468c2ecf20Sopenharmony_ci be32_to_cpu(pi->siz)); 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci strlcat(state->pp_buf, " >", PAGE_SIZE); 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci#endif 1528c2ecf20Sopenharmony_ci put_dev_sector(sect); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci strlcat(state->pp_buf, "\n", PAGE_SIZE); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci return 1; 1578c2ecf20Sopenharmony_ci} 158