Skip to content
Open
15 changes: 15 additions & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,21 @@ devices:
fastboot_set_active: true
fastboot_key_timeout: 2

- board: qdlboard
users:
- username
console: /dev/ttyUSB1
fastboot: abcdef04
qdl_programmer: /path/to/prog_firehose_ddr.elf
qdl_access:
- user: username
targets:
- boot_a
- boot_b
- user: admin
targets:
- all

- board: testboard
console: /dev/serial/by-id/usb-1234-if00-port0
name: GPIO controller board
Expand Down
4 changes: 2 additions & 2 deletions cdba-power.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ int main(int argc, char **argv)
}

if (on) {
device_power(selected_device, true);
device_power_on(selected_device, MSG_POWER_ON_NORMAL);
watch_main_loop(ready);

selected_device->usb_always_on = true;
selected_device->power_always_on = true;
} else {
device_usb(selected_device, false);
device_power(selected_device, false);
device_power_off(selected_device);
}

device_close(selected_device);
Expand Down
164 changes: 162 additions & 2 deletions cdba-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <syslog.h>

#include "cdba-server.h"
#include "cdba.h"
#include "circ_buf.h"
#include "device.h"
#include "device_parser.h"
Expand All @@ -26,6 +28,26 @@ static const char *username;

struct device *selected_device;

struct edl_file {
struct list_head node;

int fd;

char *filename;
char *target;
};

static struct list_head edl_files = LIST_INIT(edl_files);

static void edl_present(bool present)
{
uint8_t value = present ? 1 : 0;

warnx("edl is %spresent", present? "" : "not ");

cdba_send_buf(MSG_EDL_PRESENT, 1, &value);
}

static void fastboot_opened(struct fastboot *fb, void *data)
{
const uint8_t one = 1;
Expand Down Expand Up @@ -60,6 +82,7 @@ static void msg_select_board(const void *param)
fprintf(stderr, "failed to open %s\n", (const char *)param);
watch_quit();
} else {
device_edl_open(selected_device, edl_present);
device_fastboot_open(selected_device, &fastboot_ops);
}

Expand Down Expand Up @@ -93,6 +116,123 @@ static void msg_fastboot_download(const void *data, size_t len)
}
}

static struct edl_file *current_edl_file;

static void msg_edl_download(const void *data, size_t len)
{
char template[] = "/tmp/cdba.XXXXXX";
struct edl_file *edl;

edl = current_edl_file;

if (!edl) {
edl = calloc(1, sizeof(*edl));

edl->filename = strdup(template);
edl->fd = mkstemp(edl->filename);
if (edl->fd < 0)
err(1, "failed to create temporary file");

list_append(&edl_files, &edl->node);

current_edl_file = edl;
}

write(edl->fd, data, len);

if (len == 0)
close(edl->fd);
}

static void msg_edl_flash(const void *data, size_t len)
{
const char *target = data;

if (!selected_device || !current_edl_file)
return;

if (!len || target[len - 1]) {
fprintf(stderr, "invalid EDL flash target\n");
watch_quit();
return;
}

fprintf(stderr, "edl flash into '%s'\n", target);

if (!device_qdl_access_allowed(selected_device, username, target)) {
fprintf(stderr, "user '%s' is not allowed to flash EDL target '%s' on %s\n",
username, target, selected_device->board);
watch_quit();
return;
}

current_edl_file->target = strdup(target);
current_edl_file = NULL;
}

static void msg_edl_reset(void)
{
struct edl_file *edl;
const char **argv;
size_t args;
size_t arg = 0;

fprintf(stderr, "edl reset\n");

if (!selected_device) {
fprintf(stderr, "no device selected\n");
watch_quit();
return;
}

if (!selected_device->qdl_programmer) {
fprintf(stderr, "no EDL support configured for %s\n", selected_device->name);
watch_quit();
return;
}

list_for_each_entry(edl, &edl_files, node) {
if (!edl->target) {
fprintf(stderr, "EDL image without flash target\n");
watch_quit();
return;
}
}

args = 7 + list_len(&edl_files) * 3 + 1;
argv = calloc(args, sizeof(char *));

argv[arg++] = "qdl";
argv[arg++] = selected_device->qdl_programmer;

if (selected_device->qdl_storage) {
argv[arg++] = "--storage";
argv[arg++] = selected_device->qdl_storage;
}

if (selected_device->qdl_serial) {
argv[arg++] = "--serial";
argv[arg++] = selected_device->qdl_serial;
}

list_for_each_entry(edl, &edl_files, node) {
argv[arg++] = "write";
argv[arg++] = edl->target;
argv[arg++] = edl->filename;
}
argv[arg] = NULL;

if (fork() == 0) {
dup2(STDERR_FILENO, STDOUT_FILENO);
execvp("qdl", (char **)argv);
err(127, "failed to spawn qdl");
}
wait(NULL);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to bump the timeout timer somewhere around here,, as qdl flashing may take a very long time

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, although the timeout is client side - and the question is how much time one should implicitly allocate for this operation.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could utilize cdba's ux_progress and wait max(default_timeout, user_timeout) between each response?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, the flash process does provide log output which results in a stream of updates for which we could nudge the inactivity timeout. It's arriving on stderr though, for which we today don't nudge the timeout. In the event that the flash process is silent (like in cdba-axiom), this could become a problem - but perhaps worth looking at separately.

The other case where we do have a problem is the upload of large images, both MSG_FASTBOOT_DOWNLOAD and MSG_EDL_DOWNLOAD will produce a stream of packets only on "stdin", which also doesn't nudge the inactivity timeout.

It seems conceptually reasonable to me to nudge the inactivity timeout in both these cases; they are both signs of activity.


list_for_each_entry(edl, &edl_files, node)
unlink(edl->filename);
}

static void msg_fastboot_continue(void)
{
device_fastboot_continue(selected_device);
Expand Down Expand Up @@ -138,6 +278,7 @@ static int handle_stdin(int fd, void *buf)
static struct circ_buf recv_buf = { };
struct msg *msg;
struct msg hdr;
uint8_t mode;
size_t n;
int ret;

Expand Down Expand Up @@ -171,12 +312,22 @@ static int handle_stdin(int fd, void *buf)
// fprintf(stderr, "hard reset\n");
break;
case MSG_POWER_ON:
device_power(selected_device, true);
if (msg->len == 1)
mode = *(uint8_t *)msg->data;
else
mode = MSG_POWER_ON_FASTBOOT;

if (mode >= MSG_POWER_ON_COUNT) {
fprintf(stderr, "invalid power on mode requested\n");
exit(1);
}

device_power_on(selected_device, mode);

cdba_send(MSG_POWER_ON);
break;
case MSG_POWER_OFF:
device_power(selected_device, false);
device_power_off(selected_device);

cdba_send(MSG_POWER_OFF);
break;
Expand Down Expand Up @@ -210,6 +361,15 @@ static int handle_stdin(int fd, void *buf)
case MSG_KEY_PRESS:
msg_key_press(msg->data, msg->len);
break;
case MSG_EDL_DOWNLOAD:
msg_edl_download(msg->data, msg->len);
break;
case MSG_EDL_WRITE:
msg_edl_flash(msg->data, msg->len);
break;
case MSG_EDL_RESET:
msg_edl_reset();
break;
default:
fprintf(stderr, "unk %d len %d\n", msg->type, msg->len);
exit(1);
Expand Down
Loading