TypeScript icon, indicating that this package has built-in type declarations

4.0.3 • Public • Published


npm npm license npm downloads

This module implements Tizen's block map format, which maps non-empty blocks or block ranges from a raw image file, making it possible to quickly & efficiently flash the image to the target block device by only reading & writing the necessary blocks.

Install via npm

$ npm install --save blockmap


For detailed API documentation, see /doc.

const { BlockMap } = require('blockmap')

Parsing a Block Map

const blockMap = BlockMap.parse(xml)
BlockMap {
  version: '2.0',
  imageSize: 821752,
  blockSize: 4096,
  blocksCount: 201,
  mappedBlocksCount: 117,
  checksum: '44e9d58de533d5eb94f8232cff22b2e6d71b15d369c2ac2af461c63164cce324',
  checksumType: 'sha256',
  ranges: [{
    checksum: '9eaf19215d55d23de1be1fe4bed4a95bfe620a404352fd06e782738fff58e500',
    start: 0,
    end: 1
  }, {
    checksum: 'e8a26f49a71262870f8294a73f40f122d622fd70fb82bef01c0322785e9fd6b2',
    start: 3,
    end: 5
  // More ranges omitted for brevity
    checksum: 'cb732fc3f3a0f81f6a761a534201c05549c8efe4a92630ccd24241f72d7d618c',
    start: 198,
    end: 199

Creating a Block Map

Render a .bmap file from a parsed or otherwise constructed BlockMap:

const blockMap = BlockMap.parse(value)
const xml = blockMap.toString()

Where xml would look like the following, given the block map from above:

<?xml version="1.0" encoding="UTF-8"?>
<bmap version="2.0">
    <Range chksum="9eaf19215d55d23de1be1fe4bed4a95bfe620a404352fd06e782738fff58e500">0-1</Range>
    <Range chksum="e8a26f49a71262870f8294a73f40f122d622fd70fb82bef01c0322785e9fd6b2">3-5</Range>
    <!-- More ranges omitted for brevity -->
    <Range chksum="cb732fc3f3a0f81f6a761a534201c05549c8efe4a92630ccd24241f72d7d618c">198-199</Range>

NOTE: Regardless of input version, blockMap.toString() will always create a .bmap in the format of the latest version (currently 2.0).

Block Map Checksum Verification

By default, checksums for mapped ranges and the bmap file itself (only version 1.3+) will be verified when parsing or streaming. If you need to disable verification, pass false as verify parameter.

// Disable verification of the bmap file checksum:
const blockMap = BlockMap.parse(bmap, false)
const { ReadStream } = require('blockmap')
// Disable range checksum verification:
const blockReadStream = new ReadStream(fileDescriptor, blockMap, false)
const { FilterStream } = require('blockmap')
// Same for filter streams:
const filterStream = new FilterStream(blockMap, false)

Reading Mapped Blocks

NOTE: These examples just use fs.writeSync() in .on('readable') for brevity; of course this should be implemented properly in a writable stream, which the readable side (i.e. the ReadStream or FilterStream) is piped to.

Use a parsed block map to read only mapped regions:

const blockMap = BlockMap.parse(fs.readFileSync('/path/to/balena-os.bmap'))
const blockReadStream = new ReadStream(fileDescriptor, blockMap)
// The chunk emitted will have two properties set;
// 1) chunk.buffer – the data buffer
// 2) chunk.position – the chunk's offset (or address) in bytes
// Which can then be used to write only those blocks to the target:
blockReadStream.on('readable', function() {
  len chunk = null
  while(chunk = {
    fs.writeSync(fd, chunk.buffer, 0, chunk.buffer.length, chunk.position)
blockReadStream.once('end', function() {
  console.log('Read', blockReadStream.blocksRead, 'mapped blocks')
  console.log('Read', blockReadStream.bytesRead, 'mapped bytes')
  console.log('Read', blockReadStream.rangesRead, 'mapped ranges')

Filtering Unmapped Blocks

Use a filter transform to filter out unmapped blocks from a stream:

const blockMap = BlockMap.parse(fs.readFileSync('/path/to/balena-os.bmap'))
const readStream = fs.createReadStream('/path/to/balena-os.img')
const filterStream = new FilterStream(blockMap)
// The chunk emitted will have two properties set;
// 1) chunk.buffer – the data buffer
// 2) chunk.position – the chunk's offset (or address) in bytes
// Which can then be used to write only those blocks to the target:
filterStream.on('readable', function() {
  let buffer = null
  while(chunk = {
    fs.writeSync(fd, chunk.buffer, 0, chunk.buffer.length, chunk.position)
// Pipe the readable stream into the block filter:

Verifying a Flashed Device

Use a ReadStream to verify a flashed device image:

const { ReadStream } = require('blockmap');
function verify(fileDescriptor, blockMap, callback) {
  new ReadStream(fileDescriptor, blockMap).resume()
    .once('error', callback)
    .once('end', callback)
const blockMap = BlockMap.parse(fs.readFileSync('/path/to/balena-os.bmap'))
verify(fileDescriptor, blockMap, function(error) {
  if(error != null) {
    // The image didn't verify...

Handling Errors


BlockMap.parse() and blockMap.parse() will throw when encountering invalid input, or if the checksum doesn't verify:

try {
  blockMap = BlockMap.parse(value)
} catch(error) {
  // ...


If the error is due to a checksum mismatch, the error will have a .checksum and .range property, denoting the calculated checksum, and the range for which it occured:

const blockReadStream = new ReadStream(fileDescriptor, blockMap)
blockReadStream.on('error', function(error) {
  if(error.checksum) {
    console.log(`Checksum mismatch for range [${error.range.start},${error.range.end}]:`)
    console.log(`${error.checksum} != ${error.range.checksum}`)
  // ...



npm i blockmap

DownloadsWeekly Downloads






Unpacked Size

117 kB

Total Files


Last publish


  • jhermsmeier
  • jviotti