module B9.MBR ( getPartition
, PrimaryPartition (..)
, MBR(..)
, CHS(..)) where
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative
#endif
import Data.Binary.Get
import Data.Word
import Text.Printf
import qualified Data.ByteString.Lazy as BL
getPartition :: Int -> FilePath -> IO (Word64, Word64)
getPartition n f = decodeMBR <$> BL.readFile f
where
decodeMBR input =
let mbr = runGet getMBR input
part =
(case n of
1 -> mbrPart1
2 -> mbrPart2
3 -> mbrPart3
4 -> mbrPart4
b ->
error
(printf
"Error: Invalid partition index %i only partitions 1-4 are allowed. Image file: '%s'"
b
f))
mbr
start = fromIntegral (primPartLbaStart part)
len = fromIntegral (primPartSectors part)
in (start * sectorSize, len * sectorSize)
sectorSize :: Word64
sectorSize = 512
bootCodeSize :: Int
bootCodeSize = 446
data MBR = MBR { mbrPart1 :: !PrimaryPartition
, mbrPart2 :: !PrimaryPartition
, mbrPart3 :: !PrimaryPartition
, mbrPart4 :: !PrimaryPartition
}
deriving Show
data PrimaryPartition = PrimaryPartition { primPartStatus :: !Word8
, primPartChsStart :: !CHS
, primPartPartType :: !Word8
, primPartChsEnd :: !CHS
, primPartLbaStart :: !Word32
, primPartSectors :: !Word32
}
deriving Show
data CHS = CHS { chsH :: !Word8
, chs_CUpper2_S :: !Word8
, chs_CLower8 :: !Word8
}
deriving Show
getMBR :: Get MBR
getMBR = skip bootCodeSize >>
MBR <$> getPart <*> getPart <*> getPart <*> getPart
getPart :: Get PrimaryPartition
getPart = PrimaryPartition <$> getWord8
<*> getCHS
<*> getWord8
<*> getCHS
<*> getWord32le
<*> getWord32le
getCHS :: Get CHS
getCHS = CHS <$> getWord8 <*> getWord8 <*> getWord8