mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-23 03:06:38 +00:00
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:
parent
3bac0225e5
commit
4c8b97afb3
@ -16,28 +16,9 @@
|
|||||||
|
|
||||||
'use strict'
|
'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 settings = require('../models/settings')
|
||||||
const SDK = require('../../../sdk')
|
const SDK = require('../../../sdk')
|
||||||
const permissions = require('../../../shared/permissions')
|
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({
|
const scanner = SDK.createScanner({
|
||||||
blockdevice: {
|
blockdevice: {
|
||||||
@ -45,19 +26,7 @@ const scanner = SDK.createScanner({
|
|||||||
return settings.get('unsafeMode')
|
return settings.get('unsafeMode')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
usbboot: {
|
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// NOTE: Enable USBBoot on Linux if run as root
|
// NOTE: Enable USBBoot on Linux if run as root
|
||||||
|
@ -21,6 +21,14 @@ const Bluebird = require('bluebird')
|
|||||||
const EventEmitter = require('events')
|
const EventEmitter = require('events')
|
||||||
const drivelist = Bluebird.promisifyAll(require('drivelist'))
|
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
|
* @summary BlockDeviceAdapter
|
||||||
* @class
|
* @class
|
||||||
@ -68,7 +76,7 @@ class BlockDeviceAdapter extends EventEmitter {
|
|||||||
// TODO: Find a better way to detect that a certain
|
// TODO: Find a better way to detect that a certain
|
||||||
// block device is a compute module initialized
|
// block device is a compute module initialized
|
||||||
// through usbboot.
|
// 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.description = 'Compute Module'
|
||||||
drive.icon = 'raspberrypi'
|
drive.icon = 'raspberrypi'
|
||||||
drive.isSystem = false
|
drive.isSystem = false
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
const EventEmitter = require('events')
|
const EventEmitter = require('events')
|
||||||
const Bluebird = require('bluebird')
|
const Bluebird = require('bluebird')
|
||||||
const debug = require('debug')('etcher:sdk:usbboot')
|
const debug = require('debug')('etcher:sdk:usbboot')
|
||||||
@ -212,7 +214,6 @@ class USBBootAdapter extends EventEmitter {
|
|||||||
* @private
|
* @private
|
||||||
*
|
*
|
||||||
* @param {String} name - blob name
|
* @param {String} name - blob name
|
||||||
* @param {Function} fallback - fallback function
|
|
||||||
* @fulfil {Buffer} - blob
|
* @fulfil {Buffer} - blob
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*
|
*
|
||||||
@ -220,16 +221,14 @@ class USBBootAdapter extends EventEmitter {
|
|||||||
* const Bluebird = require('bluebird')
|
* const Bluebird = require('bluebird')
|
||||||
* const fs = Bluebird.promisifyAll(require('fs'))
|
* const fs = Bluebird.promisifyAll(require('fs'))
|
||||||
*
|
*
|
||||||
* const blob = adapter.queryBlobFromCache('start.elf', (name) => {
|
* const blob = adapter.queryBlobFromCache('start.elf')
|
||||||
* return fs.readFileAsync(path.join('./blobs', name))
|
|
||||||
* })
|
|
||||||
*/
|
*/
|
||||||
queryBlobFromCache (name, fallback) {
|
queryBlobFromCache (name) {
|
||||||
if (this.blobCache[name]) {
|
if (this.blobCache[name]) {
|
||||||
return Bluebird.resolve(this.blobCache[name])
|
return Bluebird.resolve(this.blobCache[name])
|
||||||
}
|
}
|
||||||
|
|
||||||
return fallback(name).tap((buffer) => {
|
return USBBootAdapter.readBlob(name).tap((buffer) => {
|
||||||
this.blobCache[name] = buffer
|
this.blobCache[name] = buffer
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -302,9 +301,7 @@ class USBBootAdapter extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_.isNil(this.progress[result.raw])) {
|
if (_.isNil(this.progress[result.raw])) {
|
||||||
this.prepare(device, {
|
this.prepare(device).catch((error) => {
|
||||||
readFile: options.readFile
|
|
||||||
}).catch((error) => {
|
|
||||||
this.emit('error', error)
|
this.emit('error', error)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -337,8 +334,6 @@ class USBBootAdapter extends EventEmitter {
|
|||||||
* @private
|
* @private
|
||||||
*
|
*
|
||||||
* @param {Object} device - node-usb device
|
* @param {Object} device - node-usb device
|
||||||
* @param {Object} options - options
|
|
||||||
* @param {Function} options.readFile - read file function
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@ -352,7 +347,7 @@ class USBBootAdapter extends EventEmitter {
|
|||||||
* console.log('Done!')
|
* console.log('Done!')
|
||||||
* })
|
* })
|
||||||
*/
|
*/
|
||||||
prepare (device, options) {
|
prepare (device) {
|
||||||
/**
|
/**
|
||||||
* @summary Set device progress
|
* @summary Set device progress
|
||||||
* @function
|
* @function
|
||||||
@ -416,7 +411,7 @@ class USBBootAdapter extends EventEmitter {
|
|||||||
const endpoint = deviceInterface.endpoint(addresses.endpoint)
|
const endpoint = deviceInterface.endpoint(addresses.endpoint)
|
||||||
|
|
||||||
if (serialNumberIndex === USB_DESCRIPTOR_NULL_INDEX) {
|
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)
|
return USBBootAdapter.writeBootCode(device, endpoint, bootcode)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -434,7 +429,6 @@ class USBBootAdapter extends EventEmitter {
|
|||||||
const STEPS_TOTAL = 38
|
const STEPS_TOTAL = 38
|
||||||
|
|
||||||
return this.startFileServer(device, endpoint, {
|
return this.startFileServer(device, endpoint, {
|
||||||
readFile: options.readFile,
|
|
||||||
progress: (step) => {
|
progress: (step) => {
|
||||||
setProgress((step * (PERCENTAGE_TOTAL - PERCENTAGE_START) / STEPS_TOTAL) + PERCENTAGE_START)
|
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} device - node-usb device
|
||||||
* @param {Object} endpoint - node-usb endpoint
|
* @param {Object} endpoint - node-usb endpoint
|
||||||
* @param {Object} options - options
|
* @param {Object} options - options
|
||||||
* @param {Function} options.readFile - read file function
|
|
||||||
* @param {Function} options.progress - progress function (step)
|
* @param {Function} options.progress - progress function (step)
|
||||||
* @param {Number} [step] - current step (used internally)
|
* @param {Number} [step] - current step (used internally)
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
@ -526,9 +519,6 @@ class USBBootAdapter extends EventEmitter {
|
|||||||
* const device = usb.findByIds(0x0a5c, 0x2763)
|
* const device = usb.findByIds(0x0a5c, 0x2763)
|
||||||
*
|
*
|
||||||
* adapter.startFileServer(device, device.interfaces(0).endpoint(1), {
|
* adapter.startFileServer(device, device.interfaces(0).endpoint(1), {
|
||||||
* readFile: (name) => {
|
|
||||||
* return fs.readFileAsync(name)
|
|
||||||
* },
|
|
||||||
* progress: (step) => {
|
* progress: (step) => {
|
||||||
* console.log(`Currently on step ${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) {
|
if (fileMessage.command === protocol.FILE_MESSAGE_COMMANDS.GET_FILE_SIZE) {
|
||||||
debug(`Getting the size of ${fileMessage.fileName}`)
|
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
|
const fileSize = fileBuffer.length
|
||||||
debug(`Sending size: ${fileSize}`)
|
debug(`Sending size: ${fileSize}`)
|
||||||
return protocol.sendBufferSize(device, fileSize)
|
return protocol.sendBufferSize(device, fileSize)
|
||||||
@ -584,7 +574,7 @@ class USBBootAdapter extends EventEmitter {
|
|||||||
if (fileMessage.command === protocol.FILE_MESSAGE_COMMANDS.READ_FILE) {
|
if (fileMessage.command === protocol.FILE_MESSAGE_COMMANDS.READ_FILE) {
|
||||||
debug(`Reading ${fileMessage.fileName}`)
|
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)
|
return protocol.write(device, endpoint, fileBuffer)
|
||||||
}).catch({
|
}).catch({
|
||||||
code: 'ENOENT'
|
code: 'ENOENT'
|
||||||
@ -613,5 +603,32 @@ class USBBootAdapter extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
USBBootAdapter.id = 'usbboot'
|
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
|
// Exports
|
||||||
module.exports = USBBootAdapter
|
module.exports = USBBootAdapter
|
||||||
|
Loading…
x
Reference in New Issue
Block a user