ff24b1f2481f5a1967c3b2a57c4cae8bd03c8acb
[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 uint32_t part_start;
41 uint32_t part_size;
42 } __attribute__((packed));
43
44 #define MBR_SIG 0xAA55
45
46 struct Mbr {
47 uint16_t mbr_code[223];
48 MbrPartition mbr_part[4];
49 uint16_t mbr_sig;
50 } __attribute__((packed));
51
52 #define MBR_FAT16 0x04
53 #define MBR_FAT32 0x0B
54 #define MBR_FAT32_INT13 0x0C
55 #define MBR_FAT16_INT13 0x0E
56 #define MBR_LINUX 0x83
57 #define MBR_NTFS 0x07
58
59 struct MbrImpl {
60 Mbr* mbr;
61 BlockDevice* mmc;
62
63 inline bool validate_signature() {
64 return reinterpret_cast<uint16_t>(mbr->mbr_sig) == MBR_SIG;
65 }
66
67 template <typename T>
68 inline bool read_block(uint8_t volume, uint32_t sector, T* dest_buffer) {
69 read_block(volume, sector, reinterpret_cast<uint32_t*>(dest_buffer));
70 }
71
72 inline unsigned int get_block_size() {
73 return mmc->block_size;
74 }
75
76 inline int get_partition_type(uint8_t volume) {
77 if (volume > 3)
78 return 0;
79 return mbr->mbr_part[volume].part_typ;
80 }
81
82 bool read_block(uint8_t volume, uint32_t sector, uint32_t* buf) {
83 if (volume > 3)
84 return false;
85
86 MbrPartition& p = mbr->mbr_part[volume];
87
88 if (p.part_typ == 0)
89 return false;
90
91 return mmc->read_block(p.part_start + sector, buf);
92 }
93
94 void read_mbr() {
95 logf("Reading master boot record ...\n");
96
97 if (!mmc->read_block(0, mbr))
98 panic("unable to read master boot record from the SD card");
99
100 if (!validate_signature())
101 panic("invalid master boot record signature (got 0x%x)", mbr->mbr_sig);
102 }
103
104 MbrImpl() {
105 mbr = new Mbr;
106 mmc = get_sdhost_device();
107 if (!mmc)
108 panic("parent block device not initilalized!");
109
110 read_mbr();
111 logf("Disk ready!\n");
112 }
113 };
114
115 MbrImpl STATIC_FILESYSTEM g_MbrDisk {};
116
117 /*****************************************************************************
118 * Wrappers for FatFS.
119 *****************************************************************************/
120
121 #include "fatfs/diskio.h"
122
123 bool g_FatFsDiskInitialized = false;
124
125 DSTATUS disk_initialize (BYTE pdrv) {
126 /* cache disk initialization state */
127 if (g_FatFsDiskInitialized) {
128 return static_cast<DRESULT>(0);
129 }
130
131 BYTE pt = g_MbrDisk.get_partition_type(pdrv);
132 switch (pt) {
133 case MBR_FAT32_INT13:
134 case MBR_FAT16_INT13:
135 case MBR_FAT32:
136 case MBR_FAT16:
137 logf("Mounting FAT partition %d of type 0x%x\n", pdrv, pt);
138 g_FatFsDiskInitialized = true;
139 return static_cast<DRESULT>(0);
140 }
141 logf("Disk %d isn't a FAT volume (partition type is 0x%x)!\n", pdrv, pt);
142 return STA_NOINIT;
143 }
144
145 DSTATUS disk_status (BYTE pdrv) {
146 return disk_initialize(pdrv);
147 }
148
149 DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
150 while (count--) {
151 g_MbrDisk.read_block(pdrv, sector, buff);
152 sector++;
153 buff += g_MbrDisk.get_block_size();
154 }
155 return (DRESULT)0;
156 }
157
158 DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff) {
159 switch (cmd) {
160 case CTRL_SYNC:
161 return (DRESULT)0;
162 case GET_SECTOR_SIZE:
163 *(WORD*)buff = g_MbrDisk.get_block_size();
164 return (DRESULT)0;
165
166 case GET_SECTOR_COUNT:
167 *(WORD*)buff = 0;
168 return (DRESULT)0;
169
170 case GET_BLOCK_SIZE:
171 *(WORD*)buff = 1;
172 return (DRESULT)0;
173 }
174 return RES_PARERR;
175 }
This page took 0.113002 seconds and 3 git commands to generate.