mirror of
https://github.com/google/pebble.git
synced 2025-05-28 22:13:13 +00:00
194 lines
5.7 KiB
C
194 lines
5.7 KiB
C
/*
|
|
* Copyright 2024 Google LLC
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "mfg_command.h"
|
|
|
|
#include "applib/app_launch_reason.h"
|
|
#include "applib/app_watch_info.h"
|
|
#include "console/prompt.h"
|
|
#include "kernel/util/standby.h"
|
|
#include "mfg/mfg_info.h"
|
|
#include "process_management/app_install_manager.h"
|
|
#include "process_management/app_manager.h"
|
|
|
|
void command_enter_standby(void) {
|
|
enter_standby(RebootReasonCode_MfgShutdown);
|
|
}
|
|
|
|
void command_color_read(void) {
|
|
char buffer[10];
|
|
prompt_send_response_fmt(buffer, sizeof(buffer), "%d", mfg_info_get_watch_color());
|
|
}
|
|
|
|
void command_color_write(const char* color_num) {
|
|
char *end;
|
|
int color = strtol(color_num, &end, 10);
|
|
|
|
if (*end) {
|
|
prompt_send_response("Invalid color");
|
|
return;
|
|
}
|
|
|
|
mfg_info_set_watch_color(color);
|
|
|
|
const WatchInfoColor written_color = mfg_info_get_watch_color();
|
|
if (written_color == color) {
|
|
prompt_send_response("OK");
|
|
} else {
|
|
prompt_send_response("ERROR");
|
|
}
|
|
}
|
|
|
|
void command_disp_offset_read(void) {
|
|
char buffer[16];
|
|
prompt_send_response_fmt(buffer, sizeof(buffer), "X: %"PRId16" Y: %"PRId16,
|
|
mfg_info_get_disp_offsets().x,
|
|
mfg_info_get_disp_offsets().y);
|
|
}
|
|
|
|
void command_disp_offset_write(const char* offset_x_str, const char* offset_y_str) {
|
|
char *nonnumeric_x, *nonnumeric_y;
|
|
int8_t offset_x = strtol(offset_x_str, &nonnumeric_x, 10);
|
|
if (*nonnumeric_x) {
|
|
prompt_send_response("Invalid x offset");
|
|
}
|
|
|
|
int8_t offset_y = strtol(offset_y_str, &nonnumeric_y, 10);
|
|
if (*nonnumeric_y) {
|
|
prompt_send_response("Invalid y offset");
|
|
}
|
|
|
|
if (!*nonnumeric_x && !*nonnumeric_y) {
|
|
mfg_info_set_disp_offsets((GPoint) {offset_x, offset_y});
|
|
}
|
|
}
|
|
|
|
void command_rtcfreq_read(void) {
|
|
char buffer[10];
|
|
prompt_send_response_fmt(buffer, sizeof(buffer), "%"PRIu32, mfg_info_get_rtc_freq());
|
|
}
|
|
|
|
void command_rtcfreq_write(const char* rtc_freq_string) {
|
|
char *end;
|
|
uint32_t rtc_freq = strtol(rtc_freq_string, &end, 10);
|
|
|
|
if (*end) {
|
|
prompt_send_response("Invalid rtcfreq");
|
|
return;
|
|
}
|
|
|
|
mfg_info_set_rtc_freq(rtc_freq);
|
|
}
|
|
|
|
void command_model_read(void) {
|
|
char model_buffer[MFG_INFO_MODEL_STRING_LENGTH];
|
|
mfg_info_get_model(model_buffer);
|
|
|
|
// Just send it straight out, as it's already null-terminated
|
|
prompt_send_response(model_buffer);
|
|
}
|
|
|
|
void command_model_write(const char* model) {
|
|
// mfg_info_set_model will truncate if the string is too long, so no need to check
|
|
mfg_info_set_model(model);
|
|
char written_model[MFG_INFO_MODEL_STRING_LENGTH];
|
|
mfg_info_get_model(written_model);
|
|
if (!strncmp(model, written_model, MFG_INFO_MODEL_STRING_LENGTH)) {
|
|
prompt_send_response("OK");
|
|
} else {
|
|
prompt_send_response("ERROR");
|
|
}
|
|
}
|
|
|
|
#if BOOTLOADER_TEST_STAGE1
|
|
#include "bootloader_test_bin.auto.h"
|
|
|
|
#include "drivers/flash.h"
|
|
#include "flash_region/flash_region.h"
|
|
#include "system/firmware_storage.h"
|
|
#include "system/bootbits.h"
|
|
#include "system/logging.h"
|
|
#include "system/reset.h"
|
|
#include "util/crc32.h"
|
|
#include "util/legacy_checksum.h"
|
|
static void prv_bootloader_test_copy(uint32_t flash_addr, uint32_t flash_end) {
|
|
const uint8_t *bin;
|
|
size_t size;
|
|
|
|
bin = s_bootloader_test_stage2;
|
|
size = sizeof(s_bootloader_test_stage2);
|
|
flash_region_erase_optimal_range(flash_addr,
|
|
flash_addr,
|
|
flash_addr+size+sizeof(FirmwareDescription),
|
|
flash_end);
|
|
|
|
FirmwareDescription fw_desc = {
|
|
.description_length = sizeof(FirmwareDescription),
|
|
.firmware_length = size,
|
|
.checksum = 0,
|
|
};
|
|
#if CAPABILITY_HAS_DEFECTIVE_FW_CRC
|
|
fw_desc.checksum = legacy_defective_checksum_memory(bin, size);
|
|
#else
|
|
fw_desc.checksum = crc32(CRC32_INIT, bin, size);
|
|
#endif
|
|
|
|
flash_write_bytes((uint8_t *)&fw_desc, flash_addr, sizeof(FirmwareDescription));
|
|
flash_write_bytes(bin, flash_addr+sizeof(FirmwareDescription), size);
|
|
}
|
|
|
|
#define BLTEST_LOG(x...) pbl_log(LOG_LEVEL_ALWAYS, __FILE__, __LINE__, x)
|
|
|
|
void command_bootloader_test(const char *dest_type) {
|
|
prompt_command_finish();
|
|
|
|
BLTEST_LOG("BOOTLOADER TEST STAGE 1");
|
|
boot_bit_set(BOOT_BIT_FW_STABLE);
|
|
|
|
BLTEST_LOG("STAGE 1 -- Setting test boot bits");
|
|
boot_bit_clear(BOOT_BIT_BOOTLOADER_TEST_A | BOOT_BIT_BOOTLOADER_TEST_B);
|
|
boot_bit_set(BOOT_BIT_BOOTLOADER_TEST_A);
|
|
|
|
bool as_fw = true;
|
|
if (strcmp(dest_type, "prf") == 0) {
|
|
as_fw = false;
|
|
}
|
|
if (as_fw) {
|
|
BLTEST_LOG("STAGE 1 -- Copying STAGE 2 to scratch");
|
|
prv_bootloader_test_copy(FLASH_REGION_FIRMWARE_SCRATCH_BEGIN,
|
|
FLASH_REGION_FIRMWARE_SCRATCH_END);
|
|
|
|
BLTEST_LOG("STAGE 1 -- Marking new FW boot bit");
|
|
boot_bit_set(BOOT_BIT_NEW_FW_AVAILABLE);
|
|
} else {
|
|
BLTEST_LOG("STAGE 1 -- Copying STAGE 2 to PRF");
|
|
flash_prf_set_protection(false);
|
|
prv_bootloader_test_copy(FLASH_REGION_SAFE_FIRMWARE_BEGIN, FLASH_REGION_SAFE_FIRMWARE_END);
|
|
|
|
BLTEST_LOG("STAGE 1 -- Marking PRF boot bit");
|
|
boot_bit_set(BOOT_BIT_FORCE_PRF);
|
|
}
|
|
|
|
BLTEST_LOG("STAGE 1 -- Rebooting");
|
|
RebootReason reason = { RebootReasonCode_PrfReset, 0 };
|
|
reboot_reason_set(&reason);
|
|
system_hard_reset();
|
|
}
|
|
#else
|
|
void command_bootloader_test(void) {
|
|
prompt_send_response("Not configured for bootloader test");
|
|
}
|
|
#endif
|