packages feed

binsm-0.1.2: binsm.hs

import Control.Monad
import qualified Data.ByteString.Lazy as BL
import Data.Maybe
import Data.Semigroup ((<>))
import Options.Applicative
import Text.PrettyPrint.ANSI.Leijen (string)

import Maps

data Opts = Opts
	{ mapFile :: String
	, extractPartition :: Maybe String
	, mergePartition :: Maybe String
	, partitionFile :: Maybe String
--	, imageFile :: Maybe String
	}

optsP :: Parser Opts
optsP = Opts
	<$> strOption
		( long "map"
		<> short 'm'
		<> metavar "FILE"
		<> helpDoc (Just $ string $ unlines [
			"Map of the binary. The default format is the linux dmesg:",
			"0x000000000000-0x000000040000 : \"u-boot\"",
			"0x000000040000-0x000000050000 : \"u-boot-env\"",
			"0x000000050000-0x000000180000 : \"kernel1\"",
			"0x000000180000-0x000000f50000 : \"rootfs\"",
			"0x000000000000-0x000001000000 : \"flash\""])
		)
	<*> optional (option str
		( long "extract"
		<> short 'e'
		<> metavar "PARTITION"
		<> help "Partition to extract"
		))
	<*> optional (option str
		( long "merge"
		<> short 'm'
		<> metavar "PARTITION"
		<> help "Partition to merge"
		))
	<*> optional (option str
		( long "partfile"
		<> short 'f'
		<> metavar "FILE"
		<> help "File to read the partition from/write partition to"
		))
{-
	<*> optional (option str
		( long "image"
		<> short 'i'
		<> metavar "FILE"
		<> help "File to read the image from"
		))
-}

getpart pnam dmap = fromMaybe (error $ "Can't find partition \"" ++ pnam ++ "\"") $ listToMaybe $ filter (\p -> name p == pnam) dmap

binsm :: Opts -> IO ()
binsm opts = do
	mapp <- Prelude.readFile $ mapFile opts
	let dmap = dmesg mapp
	when (and [extractPartition opts /= Nothing, mergePartition opts /= Nothing]) $ error "cannot extract and merge at the same time"
	img <- BL.getContents
	when (extractPartition opts /= Nothing) $ do
		let part = getpart (fromJust $ extractPartition opts) dmap
		maybe BL.putStr BL.writeFile (partitionFile opts) $ BL.drop (start part) $ BL.take (end part) img
	when (mergePartition opts /= Nothing) $ do
		let part = getpart (fromJust $ mergePartition opts) dmap
		partcont <- BL.readFile (fromMaybe (error "no partition file specified") $ partitionFile opts)
		let filelen = BL.length partcont
		let partlen = end part - start part
		when (filelen /= partlen) $ error "partition input file doesn't fit the partition"
		BL.putStr $ BL.concat [BL.take (start part) img, partcont, BL.drop (end part) img]

main = execParser (info (helper <*> optsP) mempty) >>= binsm