fix(usbboot): Move blob handling to SDK

This moves the usbboot blob handling into the SDK to avoid
root dirname conflicts through shimmed __dirname in bundled UI
and different contexts of execution.

Change-Type: patch
This commit is contained in:
Jonas Hermsmeier 2018-04-19 16:27:47 +02:00
parent 3bac0225e5
commit 4c8b97afb3
No known key found for this signature in database
GPG Key ID: 1B870F801A0CEE9F
3 changed files with 47 additions and 53 deletions

View File

@ -16,28 +16,9 @@
'use strict'
const _ = require('lodash')
const Bluebird = require('bluebird')
const fs = Bluebird.promisifyAll(require('fs'))
const path = require('path')
const settings = require('../models/settings')
const SDK = require('../../../sdk')
const permissions = require('../../../shared/permissions')
const packageJSON = require('../../../../package.json')
/**
* @summary The Etcher "blobs" directory path
* @type {String}
* @constant
*/
let BLOBS_DIRECTORY = path.join(__dirname, '..', '..', '..', 'blobs')
// FIXME: When bundled & packaged, the blob path differs
if (packageJSON.packageType !== 'local') {
BLOBS_DIRECTORY = packageJSON.packageType === 'AppImage'
? 'bin/resources/app.asar/lib/blobs'
: path.join(__dirname, '..', '..', 'blobs')
}
const scanner = SDK.createScanner({
blockdevice: {
@ -45,19 +26,7 @@ const scanner = SDK.createScanner({
return settings.get('unsafeMode')
}
},
usbboot: {
readFile: (name) => {
const isRaspberryPi = _.includes([
'bootcode.bin',
'start_cd.elf',
'fixup_cd.dat'
], name)
const blobPath = isRaspberryPi ? path.join('raspberrypi', name) : name
return fs.readFileAsync(path.join(BLOBS_DIRECTORY, 'usbboot', blobPath))
}
}
usbboot: {}
})
// NOTE: Enable USBBoot on Linux if run as root

View File

@ -21,6 +21,14 @@ const Bluebird = require('bluebird')
const EventEmitter = require('events')
const drivelist = Bluebird.promisifyAll(require('drivelist'))
const USBBOOT_RPI_COMPUTE_MODULE_NAMES = [
'0001',
'RPi-MSD- 0001',
'File-Stor Gadget',
'Linux File-Stor Gadget USB Device',
'Linux File-Stor Gadget Media'
]
/**
* @summary BlockDeviceAdapter
* @class
@ -68,7 +76,7 @@ class BlockDeviceAdapter extends EventEmitter {
// TODO: Find a better way to detect that a certain
// block device is a compute module initialized
// through usbboot.
if (_.includes([ '0001', 'RPi-MSD- 0001', 'File-Stor Gadget', 'Linux File-Stor Gadget USB Device' ], drive.description)) {
if (_.includes(USBBOOT_RPI_COMPUTE_MODULE_NAMES, drive.description)) {
drive.description = 'Compute Module'
drive.icon = 'raspberrypi'
drive.isSystem = false

View File

@ -22,6 +22,8 @@
'use strict'
const _ = require('lodash')
const fs = require('fs')
const path = require('path')
const EventEmitter = require('events')
const Bluebird = require('bluebird')
const debug = require('debug')('etcher:sdk:usbboot')
@ -212,7 +214,6 @@ class USBBootAdapter extends EventEmitter {
* @private
*
* @param {String} name - blob name
* @param {Function} fallback - fallback function
* @fulfil {Buffer} - blob
* @returns {Promise}
*
@ -220,16 +221,14 @@ class USBBootAdapter extends EventEmitter {
* const Bluebird = require('bluebird')
* const fs = Bluebird.promisifyAll(require('fs'))
*
* const blob = adapter.queryBlobFromCache('start.elf', (name) => {
* return fs.readFileAsync(path.join('./blobs', name))
* })
* const blob = adapter.queryBlobFromCache('start.elf')
*/
queryBlobFromCache (name, fallback) {
queryBlobFromCache (name) {
if (this.blobCache[name]) {
return Bluebird.resolve(this.blobCache[name])
}
return fallback(name).tap((buffer) => {
return USBBootAdapter.readBlob(name).tap((buffer) => {
this.blobCache[name] = buffer
})
}
@ -302,9 +301,7 @@ class USBBootAdapter extends EventEmitter {
}
if (_.isNil(this.progress[result.raw])) {
this.prepare(device, {
readFile: options.readFile
}).catch((error) => {
this.prepare(device).catch((error) => {
this.emit('error', error)
})
}
@ -337,8 +334,6 @@ class USBBootAdapter extends EventEmitter {
* @private
*
* @param {Object} device - node-usb device
* @param {Object} options - options
* @param {Function} options.readFile - read file function
* @returns {Promise}
*
* @example
@ -352,7 +347,7 @@ class USBBootAdapter extends EventEmitter {
* console.log('Done!')
* })
*/
prepare (device, options) {
prepare (device) {
/**
* @summary Set device progress
* @function
@ -416,7 +411,7 @@ class USBBootAdapter extends EventEmitter {
const endpoint = deviceInterface.endpoint(addresses.endpoint)
if (serialNumberIndex === USB_DESCRIPTOR_NULL_INDEX) {
return this.queryBlobFromCache(USBBOOT_BOOTCODE_FILE_NAME, options.readFile).then((bootcode) => {
return this.queryBlobFromCache(USBBOOT_BOOTCODE_FILE_NAME).then((bootcode) => {
return USBBootAdapter.writeBootCode(device, endpoint, bootcode)
})
}
@ -434,7 +429,6 @@ class USBBootAdapter extends EventEmitter {
const STEPS_TOTAL = 38
return this.startFileServer(device, endpoint, {
readFile: options.readFile,
progress: (step) => {
setProgress((step * (PERCENTAGE_TOTAL - PERCENTAGE_START) / STEPS_TOTAL) + PERCENTAGE_START)
}
@ -515,7 +509,6 @@ class USBBootAdapter extends EventEmitter {
* @param {Object} device - node-usb device
* @param {Object} endpoint - node-usb endpoint
* @param {Object} options - options
* @param {Function} options.readFile - read file function
* @param {Function} options.progress - progress function (step)
* @param {Number} [step] - current step (used internally)
* @returns {Promise}
@ -526,9 +519,6 @@ class USBBootAdapter extends EventEmitter {
* const device = usb.findByIds(0x0a5c, 0x2763)
*
* adapter.startFileServer(device, device.interfaces(0).endpoint(1), {
* readFile: (name) => {
* return fs.readFileAsync(name)
* },
* progress: (step) => {
* console.log(`Currently on step ${step}`)
* }
@ -568,7 +558,7 @@ class USBBootAdapter extends EventEmitter {
if (fileMessage.command === protocol.FILE_MESSAGE_COMMANDS.GET_FILE_SIZE) {
debug(`Getting the size of ${fileMessage.fileName}`)
return this.queryBlobFromCache(fileMessage.fileName, options.readFile).then((fileBuffer) => {
return this.queryBlobFromCache(fileMessage.fileName).then((fileBuffer) => {
const fileSize = fileBuffer.length
debug(`Sending size: ${fileSize}`)
return protocol.sendBufferSize(device, fileSize)
@ -584,7 +574,7 @@ class USBBootAdapter extends EventEmitter {
if (fileMessage.command === protocol.FILE_MESSAGE_COMMANDS.READ_FILE) {
debug(`Reading ${fileMessage.fileName}`)
return this.queryBlobFromCache(fileMessage.fileName, options.readFile).then((fileBuffer) => {
return this.queryBlobFromCache(fileMessage.fileName).then((fileBuffer) => {
return protocol.write(device, endpoint, fileBuffer)
}).catch({
code: 'ENOENT'
@ -613,5 +603,32 @@ class USBBootAdapter extends EventEmitter {
*/
USBBootAdapter.id = 'usbboot'
/**
* @summary Read a usbboot blob
* @private
*
* @param {String} filename - blob name
* @fulfil {Buffer} - blob
* @returns {Promise}
*
* @example
* USBBootAdapter.readBlob('bootcode.bin')
* .then((buffer) => { ... })
* .catch((error) => { ... })
*/
USBBootAdapter.readBlob = (filename) => {
const isRaspberryPi = _.includes([
'bootcode.bin',
'start_cd.elf',
'fixup_cd.dat'
], filename)
const blobPath = isRaspberryPi
? path.join('raspberrypi', filename)
: filename
return fs.readFileAsync(path.join(__dirname, 'blobs', blobPath))
}
// Exports
module.exports = USBBootAdapter