PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
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
12int 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
35int 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 printf("MBR disk valid_partitions=%d \n", valid_partitions);
92 FreeSysMemory(pMbrBlock);
93 return -1;
94 }
95
96 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 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 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].devNr = bd->devNr;
124 g_part_bd[partIndex].parNr = i + 1;
125 g_part_bd[partIndex].parId = pMbrBlock->primary_partitions[i].partition_type;
126 g_part_bd[partIndex].sectorSize = bd->sectorSize;
127 g_part_bd[partIndex].sectorOffset = bd->sectorOffset + (u64)pMbrBlock->primary_partitions[i].first_lba;
128 g_part_bd[partIndex].sectorCount = pMbrBlock->primary_partitions[i].sector_count;
129 bdm_connect_bd(&g_part_bd[partIndex]);
130 mountCount++;
131 }
132
133 // If one or more partitions were mounted then return success.
134 rval = mountCount > 0 ? 0 : -1;
135
136 FreeSysMemory(pMbrBlock);
137 return rval;
138}