Revert "misc cleanup"
[rpi-open-firmware.git] / arm_chainloader / drivers / mbr_disk.cc
1 /*=============================================================================
2 Copyright (C) 2016-2017 Authors of rpi-open-firmware
3 All rights reserved.
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 FILE DESCRIPTION
16 MBR based disk interface modelling primary partitions as separate disks.
17
18 =============================================================================*/
19
20 #include <stdint.h>
21 #include <chainloader.h>
22
23 #include "block_device.hpp"
24
25 #define logf(fmt, ...) printf("[MBRDISK:%s]: " fmt, __FUNCTION__, ##__VA_ARGS__);
26
27 /*****************************************************************************
28 * MBR
29 *****************************************************************************/
30
31 struct MbrPartition {
32 uint8_t part_flag; /* bootstrap flags */
33 uint8_t part_shd; /* starting head */
34 uint8_t part_ssect; /* starting sector */
35 uint8_t part_scyl; /* starting cylinder */
36 uint8_t part_typ; /* partition type */
37 uint8_t part_ehd; /* end head */
38 uint8_t part_esect; /* end sector */
39 uint8_t part_ecyl; /* end cylinder */
40 #if 0
41 uint16_t part_start_lo; /* absolute starting ... */
42 uint16_t part_start_hi; /* ... sector number */
43 uint16_t part_size_lo; /* partition size ... */
44 uint16_t part_size_hi; /* ... in sectors */
45 #endif
46 uint32_t part_start;
47 uint32_t part_size;
48 } __attribute__((packed));
49
50 #define MBR_SIG 0xAA55
51
52 struct Mbr {
53 uint16_t mbr_code[223];
54 MbrPartition mbr_part[4];
55 uint16_t mbr_sig;
56 } __attribute__((packed));
57
58 static_assert(sizeof(Mbr) >= 512, "What the fuck");
59
60 #define MBR_FAT16 0x04
61 #define MBR_FAT32 0x0B
62 #define MBR_FAT32_INT13 0x0C
63 #define MBR_FAT16_INT13 0x0E
64 #define MBR_LINUX 0x83
65 #define MBR_NTFS 0x07
66
67 static const char* mbr_fs_to_string(int fs) {
68 switch (fs) {
69 case MBR_FAT32:
70 return "FAT32";
71 case MBR_FAT32_INT13:
72 return "FAT32-INT13";
73 case MBR_FAT16_INT13:
74 return "FAT16-INT13";
75 case MBR_FAT16:
76 return "FAT16";
77 case MBR_LINUX:
78 return "Linux (ext2/ext3)";
79 case MBR_NTFS:
80 return "NTFS";
81 default:
82 return "<Unknown>";
83 }
84 }
85
86 struct MbrImpl {
87 Mbr* mbr;
88 BlockDevice* mmc;
89
90 inline bool validate_signature() {
91 return reinterpret_cast<uint16_t>(mbr->mbr_sig) == MBR_SIG;
92 }
93
94 template <typename T>
95 inline bool read_block(uint8_t volume, uint32_t sector, T* dest_buffer) {
96 read_block(volume, sector, reinterpret_cast<uint32_t*>(dest_buffer));
97 }
98
99 inline unsigned int get_block_size() {
100 return mmc->block_size;
101 }
102
103 inline int get_partition_type(uint8_t volume) {
104 if (volume > 3)
105 return 0;
106 return mbr->mbr_part[volume].part_typ;
107 }
108
109 bool read_block(uint8_t volume, uint32_t sector, uint32_t* buf) {
110 if (volume > 3)
111 return false;
112
113 MbrPartition& p = mbr->mbr_part[volume];
114
115 if (p.part_typ == 0)
116 return false;
117
118 return mmc->read_block(p.part_start + sector, buf);
119 }
120
121 void read_mbr() {
122 logf("Reading master boot record ...\n");
123
124 if (!mmc->read_block(0, mbr)) {
125 panic("unable to read master boot record from the SD card");
126 }
127
128 if (!validate_signature()) {
129 panic("invalid master boot record signature (got 0x%x)", mbr->mbr_sig);
130 }
131
132 logf("MBR contents:\n");
133
134 for (int i = 0; i < 4; i++) {
135 MbrPartition& p = mbr->mbr_part[i];
136 printf(" %d: %s at:%d size:%d\n", i, mbr_fs_to_string(p.part_typ), p.part_start, p.part_size);
137 }
138 }
139
140 MbrImpl() {
141 mbr = new Mbr;
142 mmc = get_sdhost_device();
143 if (!mmc) {
144 panic("parent block device not initilalized!");
145 }
146 read_mbr();
147 logf("Disk ready!\n");
148 }
149 };
150
151 MbrImpl STATIC_FILESYSTEM g_MbrDisk {};
152
153 /*****************************************************************************
154 * Wrappers for FatFS.
155 *****************************************************************************/
156
157 #include "fatfs/diskio.h"
158
159 bool g_FatFsDiskInitialized = false;
160
161 DSTATUS disk_initialize (BYTE pdrv) {
162 /* cache disk initialization state */
163 if (g_FatFsDiskInitialized) {
164 return static_cast<DRESULT>(0);
165 }
166
167 BYTE pt = g_MbrDisk.get_partition_type(pdrv);
168 switch (pt) {
169 case MBR_FAT32_INT13:
170 case MBR_FAT16_INT13:
171 case MBR_FAT32:
172 case MBR_FAT16:
173 logf("Mounting FAT partition %d of type 0x%x\n", pdrv, pt);
174 g_FatFsDiskInitialized = true;
175 return static_cast<DRESULT>(0);
176 }
177 logf("Disk %d isn't a FAT volume (partition type is 0x%x)!\n", pdrv, pt);
178 return STA_NOINIT;
179 }
180
181 DSTATUS disk_status (BYTE pdrv) {
182 return disk_initialize(pdrv);
183 }
184
185 DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
186 while (count--) {
187 g_MbrDisk.read_block(pdrv, sector, buff);
188 sector++;
189 buff += g_MbrDisk.get_block_size();
190 }
191 return (DRESULT)0;
192 }
193
194 DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff) {
195 switch (cmd) {
196 case CTRL_SYNC:
197 return (DRESULT)0;
198 case GET_SECTOR_SIZE:
199 *(WORD*)buff = g_MbrDisk.get_block_size();
200 return (DRESULT)0;
201
202 case GET_SECTOR_COUNT:
203 *(WORD*)buff = 0;
204 return (DRESULT)0;
205
206 case GET_BLOCK_SIZE:
207 *(WORD*)buff = 1;
208 return (DRESULT)0;
209 }
210 return RES_PARERR;
211 }
This page took 0.096343 seconds and 4 git commands to generate.