debugging
[rpi-open-firmware.git] / arm_chainloader / drivers / mbr_disk.cc
1 /*=============================================================================
2 Copyright (C) 2016 Kristina Brooks
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: return "FAT32"; break;
70 case MBR_FAT32_INT13: return "FAT32-INT13"; break;
71 case MBR_FAT16_INT13: return "FAT16-INT13"; break;
72 case MBR_FAT16: return "FAT16"; break;
73 case MBR_LINUX: return "Linux (ext2/ext3)"; break;
74 case MBR_NTFS: return "NTFS"; break;
75 default: return "<Unknown>";
76 }
77 }
78
79 struct MbrImpl {
80 Mbr* mbr;
81 BlockDevice* mmc;
82
83 inline bool validate_signature() {
84 return reinterpret_cast<uint16_t>(mbr->mbr_sig) == MBR_SIG;
85 }
86
87 template <typename T>
88 inline bool read_block(uint8_t volume, uint32_t sector, T* dest_buffer) {
89 read_block(volume, sector, reinterpret_cast<uint32_t*>(dest_buffer));
90 }
91
92 inline unsigned int get_block_size() {
93 return mmc->block_size;
94 }
95
96 inline int get_partition_type(uint8_t volume) {
97 if (volume > 3)
98 return 0;
99 return mbr->mbr_part[volume].part_typ;
100 }
101
102 bool read_block(uint8_t volume, uint32_t sector, uint32_t* buf) {
103 if (volume > 3)
104 return false;
105
106 MbrPartition& p = mbr->mbr_part[volume];
107
108 if (p.part_typ == 0)
109 return false;
110
111 return mmc->read_block(p.part_start + sector, buf);
112 }
113
114 void read_mbr() {
115 logf("Reading master boot record ...\n");
116
117 if (!mmc->read_block(0, mbr)) {
118 panic("unable to read master boot record from the SD card");
119 }
120
121 if (!validate_signature()) {
122 /* poke the VPU */
123 volatile unsigned int* mail = (volatile unsigned int*) 0x2000B8A0;
124 while(1) *mail = 0xA1755A01;
125 panic("invalid master boot record signature (got 0x%x)", mbr->mbr_sig);
126 }
127
128 logf("MBR contents:\n");
129
130 for (int i = 0; i < 4; i++) {
131 MbrPartition& p = mbr->mbr_part[i];
132 printf(" %d: %s at:%d size:%d\n", i, mbr_fs_to_string(p.part_typ), p.part_start, p.part_size);
133 }
134 }
135
136 MbrImpl() {
137 mbr = new Mbr;
138 mmc = get_sdhost_device();
139 if (!mmc) {
140 panic("parent block device not initilalized!");
141 }
142 read_mbr();
143 logf("Disk ready!\n");
144 }
145 };
146
147 MbrImpl STATIC_FILESYSTEM g_MbrDisk {};
148
149 /*****************************************************************************
150 * Wrappers for FatFS.
151 *****************************************************************************/
152
153 #include "fatfs/diskio.h"
154
155 DSTATUS disk_initialize (BYTE pdrv) {
156 BYTE pt = g_MbrDisk.get_partition_type(pdrv);
157 switch (pt) {
158 case MBR_FAT32_INT13:
159 case MBR_FAT16_INT13:
160 case MBR_FAT32:
161 case MBR_FAT16:
162 logf("Mounting FAT partition %d of type 0x%x\n", pdrv, pt);
163 return (DRESULT)0;
164 }
165 logf("Disk %d isn't a FAT volume (partition type is 0x%x)!\n", pdrv, pt);
166 return STA_NOINIT;
167 }
168
169 DSTATUS disk_status (BYTE pdrv) {
170 return disk_initialize(pdrv);
171 }
172
173 DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
174 while (count--)
175 {
176 g_MbrDisk.read_block(pdrv, sector, buff);
177 sector++;
178 buff += g_MbrDisk.get_block_size();
179 }
180 return (DRESULT)0;
181 }
182
183 DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff) {
184 switch (cmd)
185 {
186 case CTRL_SYNC:
187 return (DRESULT)0;
188 case GET_SECTOR_SIZE:
189 *(WORD*)buff = g_MbrDisk.get_block_size();
190 return (DRESULT)0;
191
192 case GET_SECTOR_COUNT:
193 *(WORD*)buff = 0;
194 return (DRESULT)0;
195
196 case GET_BLOCK_SIZE:
197 *(WORD*)buff = 1;
198 return (DRESULT)0;
199 }
200 return RES_PARERR;
201 }
This page took 0.096055 seconds and 5 git commands to generate.