PS2SDK
PS2 Homebrew Libraries
part_driver_mbr.c
1 #include "part_driver.h"
2 #include <errno.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <sysmem.h>
6 
7 #include <bdm.h>
8 #include "mbr_types.h"
9 
10 #include "module_debug.h"
11 
12 int partitions_sanity_check_mbr(struct block_device *bd, master_boot_record* pMbrBlock) {
13  //All 4 MBR partitions should be considered valid ones to be mounted, even if some are unused.
14  //At least one of them must be active.
15  int valid = 0;
16  int active = 0;
17 
18  for (int i = 0; i < 4; i++)
19  {
20 
21  if (pMbrBlock->primary_partitions[i].partition_type != 0) {
22 
23  if((pMbrBlock->primary_partitions[i].first_lba == 0) || (pMbrBlock->primary_partitions[i].first_lba >= bd->sectorCount))
24  return 0; //invalid
25 
26  active++;
27  }
28 
29  valid++; //Considered at least a valid partition.
30  }
31 
32  return (valid == 4) && (active > 0);
33 }
34 
35 int part_connect_mbr(struct block_device *bd)
36 {
37  master_boot_record* pMbrBlock = NULL;
38  int rval = -1;
39  int ret;
40  int mountCount = 0;
41  int partIndex;
42  int valid_partitions;
43 
44  M_DEBUG("%s\n", __func__);
45 
46  // Filter out any block device where sectorOffset != 0, as this will be a block device for a file system partition and not
47  // the raw device.
48  if (bd->sectorOffset != 0)
49  return rval;
50 
51  // Allocate memory for MBR partition sector.
52  pMbrBlock = AllocSysMemory(ALLOC_FIRST, sizeof(master_boot_record), NULL);
53  if (pMbrBlock == NULL)
54  {
55  // Failed to allocate memory for mbr block.
56  M_DEBUG("Failed to allocate memory for MBR block\n");
57  return rval;
58  }
59 
60  // Read the MBR block from the block device.
61  ret = bd->read(bd, 0, pMbrBlock, 1);
62  if (ret < 0)
63  {
64  // Failed to read MBR block from the block device.
65  M_DEBUG("Failed to read MBR sector from block device %d\n", ret);
66  return rval;
67  }
68 
69  // Check the MBR boot signature.
70  if (pMbrBlock->boot_signature != MBR_BOOT_SIGNATURE)
71  {
72  // Boot signature is invalid, device is not valid MBR.
73  M_DEBUG("MBR boot signature is invalid, device is not MBR\n");
74  FreeSysMemory(pMbrBlock);
75  return rval;
76  }
77 
78  // Check the first primary partition to see if this is a GPT protective MBR.
79  if (pMbrBlock->primary_partitions[0].partition_type == MBR_PART_TYPE_GPT_PROTECTIVE_MBR)
80  {
81  // We explicitly fail to connect GPT protective MBRs in order to let the GPT driver handle it.
82  FreeSysMemory(pMbrBlock);
83  return rval;
84  }
85 
86 
87  valid_partitions = partitions_sanity_check_mbr(bd, pMbrBlock);
88 
89  //Most likely a VBR
90  if(valid_partitions == 0) {
91  M_PRINTF("MBR disk valid_partitions=%d \n", valid_partitions);
92  FreeSysMemory(pMbrBlock);
93  return -1;
94  }
95 
96  M_PRINTF("Found MBR disk\n");
97 
98  // Loop and parse the primary partition entries in the MBR block.
99  for (int i = 0; i < 4; i++)
100  {
101  // Check if the partition is active, checking the status bit is not reliable so check if the sector_count is greater than zero instead.
102  if (pMbrBlock->primary_partitions[i].sector_count == 0)
103  continue;
104 
105  //Ignore partitions that are not active. 0 is empty partition_type.
106  if (pMbrBlock->primary_partitions[i].partition_type == 0)
107  continue;
108 
109  M_PRINTF("Found partition type 0x%02x\n", pMbrBlock->primary_partitions[i].partition_type);
110 
111  // TODO: Filter out unsupported partition types.
112 
113  if ((partIndex = GetNextFreePartitionIndex()) == -1)
114  {
115  // No more free partition slots.
116  M_PRINTF("Can't mount partition, no more free partition slots!\n");
117  continue;
118  }
119 
120  // Create the pseudo block device for the partition.
121  g_part[partIndex].bd = bd;
122  g_part_bd[partIndex].name = bd->name;
123  g_part_bd[partIndex].path = bd->path;
124  g_part_bd[partIndex].devNr = bd->devNr;
125  g_part_bd[partIndex].parNr = i + 1;
126  g_part_bd[partIndex].parId = pMbrBlock->primary_partitions[i].partition_type;
127  g_part_bd[partIndex].sectorSize = bd->sectorSize;
128  g_part_bd[partIndex].sectorOffset = bd->sectorOffset + (u64)pMbrBlock->primary_partitions[i].first_lba;
129  g_part_bd[partIndex].sectorCount = pMbrBlock->primary_partitions[i].sector_count;
130  bdm_connect_bd(&g_part_bd[partIndex]);
131  mountCount++;
132  }
133 
134  // If one or more partitions were mounted then return success.
135  rval = mountCount > 0 ? 0 : -1;
136 
137  FreeSysMemory(pMbrBlock);
138  return rval;
139 }
bdm.h
mbr_types.h
stdio.h
sysmem.h
block_device
Definition: bdm.h:21
errno.h