cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id);
static void i2c_other(message * m, int ipc_status);
-/* SEF callbacks and driver state management */
-static int sef_cb_lu_state_save(int);
-static int lu_state_restore(void);
-static int sef_cb_init(int type, sef_init_info_t * info);
-static void sef_local_startup(void);
-
/* Globals */
/* the bus that this instance of the driver is responsible for */
.cdr_other = i2c_other
};
+static int
+sef_cb_lu_state_save(int UNUSED(result), int UNUSED(flags))
+{
+ int r;
+ char key[DS_MAX_KEYLEN];
+
+ memset(key, '\0', DS_MAX_KEYLEN);
+ snprintf(key, DS_MAX_KEYLEN, "i2c.%d.i2cdev", i2c_bus_id + 1);
+ r = ds_publish_mem(key, i2cdev, sizeof(i2cdev), DSF_OVERWRITE);
+ if (r != OK) {
+ log_warn(&log, "ds_publish_mem(%s) failed (r=%d)\n", key, r);
+ return r;
+ }
+
+ log_debug(&log, "State Saved\n");
+
+ return OK;
+}
+
/*
* Claim an unclaimed device for exclusive use by endpt. This function can
* also be used to update the endpt if the endpt's label matches the label
i2cdev[slave_addr].endpt = endpt;
memcpy(i2cdev[slave_addr].key, key, DS_MAX_KEYLEN);
- sef_cb_lu_state_save(0); /* save reservations */
+ sef_cb_lu_state_save(0, 0); /* save reservations */
log_debug(&log, "Device 0x%x claimed by 0x%x key='%s'\n",
slave_addr, endpt, key);
}
}
-static int
-sef_cb_lu_state_save(int UNUSED(state))
-{
- int r;
- char key[DS_MAX_KEYLEN];
-
- memset(key, '\0', DS_MAX_KEYLEN);
- snprintf(key, DS_MAX_KEYLEN, "i2c.%d.i2cdev", i2c_bus_id + 1);
- r = ds_publish_mem(key, i2cdev, sizeof(i2cdev), DSF_OVERWRITE);
- if (r != OK) {
- log_warn(&log, "ds_publish_mem(%s) failed (r=%d)\n", key, r);
- return r;
- }
-
- log_debug(&log, "State Saved\n");
-
- return OK;
-}
-
static int
lu_state_restore(void)
{
}
/* Save state */
- sef_cb_lu_state_save(0);
+ sef_cb_lu_state_save(0, 0);
/* Initialization completed successfully. */
return OK;
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x00
};
-/* SEF functions and variables. */
-static void sef_local_startup(void);
-static int sef_cb_init(int type, sef_init_info_t * info);
-static int sef_cb_lu_state_save(int);
-static int lu_state_restore(void);
-
/* libblockdriver callbacks */
static int cat24c256_blk_open(devminor_t minor, int access);
static int cat24c256_blk_close(devminor_t minor);
}
static int
-sef_cb_lu_state_save(int UNUSED(state))
+sef_cb_lu_state_save(int UNUSED(result), int UNUSED(flags))
{
ds_publish_u32("bus", bus, DSF_OVERWRITE);
ds_publish_u32("address", address, DSF_OVERWRITE);
/* SEF functions and variables. */
static void sef_local_startup(void);
static int sef_cb_init(int type, sef_init_info_t *info);
-static int sef_cb_lu_state_save(int);
+static int sef_cb_lu_state_save(int, int);
static int lu_state_restore(void);
/* Entry points to the hello driver. */
return size;
}
-static int sef_cb_lu_state_save(int UNUSED(state)) {
+static int sef_cb_lu_state_save(int UNUSED(state), int UNUSED(flags)) {
/* Save the state. */
ds_publish_u32("open_counter", open_counter, DSF_OVERWRITE);
/*===========================================================================*
* sef_cb_lu_state_isvalid *
*===========================================================================*/
-int sef_cb_lu_state_isvalid(int state)
+int sef_cb_lu_state_isvalid(int state, int UNUSED(flags))
{
return SEF_LU_STATE_IS_STANDARD(state) || RL_STATE_IS_CUSTOM(state);
}
static int intr_handler(void);
static void do_shutdown(int how);
-/* SEF Related Function Prototypes */
-static void sef_local_startup(void);
-static int sef_cb_lu_state_save(int);
-static int lu_state_restore(void);
-static int sef_cb_init(int type, sef_init_info_t * info);
-
static int
check_revision(void)
{
}
static int
-sef_cb_lu_state_save(int UNUSED(state))
+sef_cb_lu_state_save(int UNUSED(result), int UNUSED(flags))
{
ds_publish_u32("bus", bus, DSF_OVERWRITE);
ds_publish_u32("address", address, DSF_OVERWRITE);
/* local functions */
static int check_revision(void);
-/* SEF related functions */
-static void sef_local_startup(void);
-static int sef_cb_lu_state_save(int);
-static int lu_state_restore(void);
-static int sef_cb_init(int type, sef_init_info_t * info);
-
/* functions for transfering struct tm to/from this driver and calling proc. */
static int fetch_t(endpoint_t ep, cp_grant_id_t gid, struct tm *t);
static int store_t(endpoint_t ep, cp_grant_id_t gid, struct tm *t);
}
static int
-sef_cb_lu_state_save(int UNUSED(state))
+sef_cb_lu_state_save(int UNUSED(result), int UNUSED(flags))
{
/* The addresses are fixed/non-configurable so bus is the only state */
ds_publish_u32("bus", bus, DSF_OVERWRITE);
/*===========================================================================*
* sef_cb_lu_state_isvalid *
*===========================================================================*/
-int sef_cb_lu_state_isvalid(int state)
+int sef_cb_lu_state_isvalid(int state, int UNUSED(flags))
{
return SEF_LU_STATE_IS_STANDARD(state) || PR_STATE_IS_CUSTOM(state);
}
static void sef_local_startup(void);
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
EXTERN int sef_cb_lu_prepare(int state);
-EXTERN int sef_cb_lu_state_isvalid(int state);
+EXTERN int sef_cb_lu_state_isvalid(int state, int flags);
EXTERN void sef_cb_lu_state_dump(int state);
/* Entry points to this driver. */
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
static void bmp085_other(message * m, int ipc_status);
-/* SEF Function */
-static int sef_cb_lu_state_save(int);
-static int lu_state_restore(void);
-static int sef_cb_init(int type, sef_init_info_t * info);
-static void sef_local_startup(void);
-
/* Entry points to this driver from libchardriver. */
static struct chardriver bmp085_tab = {
.cdr_read = bmp085_read,
}
static int
-sef_cb_lu_state_save(int UNUSED(state))
+sef_cb_lu_state_save(int UNUSED(result), int UNUSED(flags))
{
ds_publish_u32("bus", bus, DSF_OVERWRITE);
ds_publish_u32("address", address, DSF_OVERWRITE);
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
static void sht21_other(message * m, int ipc_status);
-/* SEF functions */
-static int sef_cb_lu_state_save(int);
-static int lu_state_restore(void);
-static int sef_cb_init(int type, sef_init_info_t * info);
-static void sef_local_startup(void);
-
/* Entry points to this driver from libchardriver. */
static struct chardriver sht21_tab = {
.cdr_read = sht21_read,
}
static int
-sef_cb_lu_state_save(int UNUSED(state))
+sef_cb_lu_state_save(int UNUSED(result), int UNUSED(flags))
{
ds_publish_u32("bus", bus, DSF_OVERWRITE);
ds_publish_u32("address", address, DSF_OVERWRITE);
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
static void tsl2550_other(message * m, int ipc_status);
-/* SEF functions */
-static int sef_cb_lu_state_save(int);
-static int lu_state_restore(void);
-static int sef_cb_init(int type, sef_init_info_t * info);
-static void sef_local_startup(void);
-
/* Entry points to this driver from libchardriver. */
static struct chardriver tsl2550_tab = {
.cdr_read = tsl2550_read,
}
static int
-sef_cb_lu_state_save(int UNUSED(state))
+sef_cb_lu_state_save(int UNUSED(result), int UNUSED(flags))
{
ds_publish_u32("bus", bus, DSF_OVERWRITE);
ds_publish_u32("address", address, DSF_OVERWRITE);
#define ATA_IF_NATIVE1 (1L << 2) /* second channel is in native mode */
extern int sef_cb_lu_prepare(int state);
-extern int sef_cb_lu_state_isvalid(int state);
+extern int sef_cb_lu_state_isvalid(int state, int flags);
extern void sef_cb_lu_state_dump(int state);
/*===========================================================================*
* sef_cb_lu_state_isvalid *
*===========================================================================*/
-int sef_cb_lu_state_isvalid(int state)
+int sef_cb_lu_state_isvalid(int state, int UNUSED(flags))
{
return SEF_LU_STATE_IS_STANDARD(state) || AT_STATE_IS_CUSTOM(state);
}
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
static void sef_cb_signal_handler(int signo);
EXTERN int sef_cb_lu_prepare(int state);
-EXTERN int sef_cb_lu_state_isvalid(int state);
+EXTERN int sef_cb_lu_state_isvalid(int state, int flags);
EXTERN void sef_cb_lu_state_dump(int state);
int last_was_write;
/*===========================================================================*
* sef_cb_lu_state_isvalid *
*===========================================================================*/
-int sef_cb_lu_state_isvalid(int state)
+int sef_cb_lu_state_isvalid(int state, int UNUSED(flags))
{
return SEF_LU_STATE_IS_STANDARD(state) || FL_STATE_IS_CUSTOM(state);
}
/*===========================================================================*
* sef_cb_lu_state_isvalid *
*===========================================================================*/
-int sef_cb_lu_state_isvalid(int state)
+int sef_cb_lu_state_isvalid(int state, int UNUSED(flags))
{
return SEF_LU_STATE_IS_STANDARD(state) || LOG_STATE_IS_CUSTOM(state);
}
static void sef_local_startup(void);
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
EXTERN int sef_cb_lu_prepare(int state);
-EXTERN int sef_cb_lu_state_isvalid(int state);
+EXTERN int sef_cb_lu_state_isvalid(int state, int flags);
EXTERN void sef_cb_lu_state_dump(int state);
static void sef_cb_signal_handler(int signo);
static int do_pan_display(int minor, endpoint_t ep, cp_grant_id_t gid);
static int keep_displaying_restarted(void);
-/* SEF functions and variables. */
-static void sef_local_startup(void);
-static int sef_cb_init(int type, sef_init_info_t *info);
-static int sef_cb_lu_state_save(int);
-static int lu_state_restore(void);
-
/* Entry points to the fb driver. */
static struct chardriver fb_tab =
{
}
static int
-sef_cb_lu_state_save(int UNUSED(state)) {
+sef_cb_lu_state_save(int UNUSED(result), int UNUSED(flags))
+{
/* Save the state. */
ds_publish_u32("open_counter", open_counter[0], DSF_OVERWRITE);
return OK;
}
-static void
-sef_local_startup()
-{
- /* Register init callbacks. Use the same function for all event types */
- sef_setcb_init_fresh(sef_cb_init);
- sef_setcb_init_lu(sef_cb_init);
- sef_setcb_init_restart(sef_cb_init);
-
- /* Register live update callbacks */
- /* - Agree to update immediately when LU is requested in a valid state*/
- sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
- /* - Support live update starting from any standard state */
- sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
- /* - Register a custom routine to save the state. */
- sef_setcb_lu_state_save(sef_cb_lu_state_save);
-
- /* Let SEF perform startup. */
- sef_startup();
-}
-
static int
sef_cb_init(int type, sef_init_info_t *UNUSED(info))
{
return OK;
}
+static void
+sef_local_startup()
+{
+ /* Register init callbacks. Use the same function for all event types */
+ sef_setcb_init_fresh(sef_cb_init);
+ sef_setcb_init_lu(sef_cb_init);
+ sef_setcb_init_restart(sef_cb_init);
+
+ /* Register live update callbacks */
+ /* - Agree to update immediately when LU is requested in a valid state*/
+ sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
+ /* - Support live update starting from any standard state */
+ sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
+ /* - Register a custom routine to save the state. */
+ sef_setcb_lu_state_save(sef_cb_lu_state_save);
+
+ /* Let SEF perform startup. */
+ sef_startup();
+}
+
int
main(int argc, char *argv[])
{
.log_func = default_log
};
-static void sef_local_startup(void);
-static int sef_cb_lu_state_save(int);
-static int lu_state_restore(void);
-static int sef_cb_init(int type, sef_init_info_t * info);
-
/* CEC Module */
static int is_display_connected(void);
static int enable_hdmi_module(void);
}
static int
-sef_cb_lu_state_save(int UNUSED(state))
+sef_cb_lu_state_save(int UNUSED(result), int UNUSED(flags))
{
ds_publish_u32("cec_bus", cec_bus, DSF_OVERWRITE);
ds_publish_u32("hdmi_bus", hdmi_bus, DSF_OVERWRITE);
int result;
int state;
int prepare_maxtime;
- uint8_t padding[44];
+ int flags;
+ uint8_t padding[40];
} mess_rs_update;
_ASSERT_MSG_SIZE(mess_rs_update);
/* Callback type definitions. */
typedef int(*sef_cb_lu_prepare_t)(int);
-typedef int(*sef_cb_lu_state_isvalid_t)(int);
+typedef int(*sef_cb_lu_state_isvalid_t)(int, int);
typedef void(*sef_cb_lu_state_changed_t)(int, int);
typedef void(*sef_cb_lu_state_dump_t)(int);
-typedef int(*sef_cb_lu_state_save_t)(int);
+typedef int(*sef_cb_lu_state_save_t)(int, int);
typedef int(*sef_cb_lu_response_t)(message *m_ptr);
/* Callback registration helpers. */
/* Predefined callback implementations. */
int sef_cb_lu_prepare_null(int state);
-int sef_cb_lu_state_isvalid_null(int state);
+int sef_cb_lu_state_isvalid_null(int state, int flags);
void sef_cb_lu_state_changed_null(int old_state, int state);
void sef_cb_lu_state_dump_null(int state);
-int sef_cb_lu_state_save_null(int state);
+int sef_cb_lu_state_save_null(int state, int flags);
int sef_cb_lu_response_null(message *m_ptr);
int sef_cb_lu_prepare_always_ready(int state);
int sef_cb_lu_prepare_never_ready(int state);
int sef_cb_lu_prepare_crash(int state);
-int sef_cb_lu_state_isvalid_standard(int state);
-int sef_cb_lu_state_isvalid_workfree(int state);
+int sef_cb_lu_state_isvalid_standard(int state, int flags);
+int sef_cb_lu_state_isvalid_workfree(int state, int flags);
+int sef_cb_lu_state_isvalid_workfree_self(int state, int flags);
+int sef_cb_lu_state_isvalid_generic(int state, int flags);
int sef_cb_lu_response_rs_reply(message *m_ptr);
/* Macros for predefined callback implementations. */
#define SEF_LU_STATE_WORK_FREE 1 /* no work in progress */
#define SEF_LU_STATE_REQUEST_FREE 2 /* no request in progress */
#define SEF_LU_STATE_PROTOCOL_FREE 3 /* no protocol in progress */
-#define SEF_LU_STATE_CUSTOM_BASE (SEF_LU_STATE_PROTOCOL_FREE+1)
-#define SEF_LU_STATE_IS_STANDARD(s) ((s) > SEF_LU_STATE_NULL \
+#define SEF_LU_STATE_EVAL 4 /* evaluate expression */
+
+#define SEF_LU_STATE_UNREACHABLE 5 /* unreachable state */
+#define SEF_LU_STATE_PREPARE_CRASH 6 /* crash at prepare time */
+
+#define SEF_LU_STATE_STD_BASE (SEF_LU_STATE_WORK_FREE)
+#define SEF_LU_STATE_DEBUG_BASE (SEF_LU_STATE_UNREACHABLE)
+#define SEF_LU_STATE_CUSTOM_BASE (SEF_LU_STATE_PREPARE_CRASH+1)
+
+#define SEF_LU_STATE_IS_STANDARD(s) ((s) >= SEF_LU_STATE_STD_BASE \
+ && (s) < SEF_LU_STATE_CUSTOM_BASE \
+ && (SEF_LU_ALWAYS_ALLOW_DEBUG_STATES || !SEF_LU_STATE_IS_DEBUG(s)))
+#define SEF_LU_STATE_IS_DEBUG(s) ((s) >= SEF_LU_STATE_DEBUG_BASE \
&& (s) < SEF_LU_STATE_CUSTOM_BASE)
+#define SEF_LU_STATE_EVAL_MAX_LEN 512
+
+/* Live update flags (can be used as init flags as well). */
+#define SEF_LU_SELF 0x0100 /* this is a self update */
+#define SEF_LU_ASR 0x0200 /* this is an ASR update */
+#define SEF_LU_MULTI 0x0400 /* this is a multi-component update */
+#define SEF_LU_INCLUDES_VM 0x0800 /* the update includes VM */
+#define SEF_LU_INCLUDES_RS 0x1000 /* the update includes RS */
+#define SEF_LU_PREPARE_ONLY 0x2000 /* prepare only, no actual update taking place */
+#define SEF_LU_UNSAFE 0x4000 /* unsafe update, rollback may not be possible */
+#define SEF_LU_NOMMAP 0x8000 /* update doesn't inherit mmapped regions */
+#define SEF_LU_DETACHED 0x10000 /* update detaches the old instance */
+
+#define SEF_LU_IS_IDENTITY_UPDATE(F) (((F) & (SEF_LU_SELF|SEF_LU_NOMMAP|SEF_LU_ASR|SEF_INIT_ST)) == SEF_LU_SELF)
+
/* Debug. */
#define SEF_LU_DEBUG_DEFAULT 1
+#define SEF_LU_ALWAYS_ALLOW_DEBUG_STATES 1
#ifndef SEF_LU_DEBUG
#define SEF_LU_DEBUG SEF_LU_DEBUG_DEFAULT
/* SEF Live update variables. */
static int sef_lu_state;
+static int sef_lu_flags;
+
+extern __attribute__((weak)) int st_do_state_cleanup(void);
/* SEF Live update callbacks. */
static struct sef_cbs {
int do_sef_lu_request(message *m_ptr)
{
/* Handle a SEF Live update request. */
- int state, old_state, is_valid_state;
+ int state, old_state, flags, is_valid_state;
sef_lu_debug_cycle = 0;
old_state = sef_lu_state;
state = m_ptr->m_rs_update.state;
+ flags = m_ptr->m_rs_update.flags;
/* Deal with prepare cancel requests first. */
is_valid_state = (state == SEF_LU_STATE_NULL);
/* Otherwise only accept live update requests with a valid state. */
- is_valid_state = is_valid_state || sef_cbs.sef_cb_lu_state_isvalid(state);
+ is_valid_state = SEF_LU_ALWAYS_ALLOW_DEBUG_STATES && SEF_LU_STATE_IS_DEBUG(state);
+ is_valid_state = is_valid_state || sef_cbs.sef_cb_lu_state_isvalid(state, flags);
if(!is_valid_state) {
- if(sef_cbs.sef_cb_lu_state_isvalid == SEF_CB_LU_STATE_ISVALID_NULL) {
+ if(sef_cbs.sef_cb_lu_state_isvalid == SEF_CB_LU_STATE_ISVALID_DEFAULT) {
sef_lu_ready(ENOSYS);
}
else {
static void sef_lu_ready(int result)
{
message m;
- int old_state, r;
+ int old_state, r=EINVAL;
#if SEF_LU_DEBUG
sef_lu_debug_begin();
sef_lu_debug_end();
#endif
- /* If result is OK, let the callback code save
+ /* If result is OK, let the callback code cleanup and save
* any state that must be carried over to the new version.
*/
if(result == OK) {
- r = sef_cbs.sef_cb_lu_state_save(sef_lu_state);
+ /* st_do_state_cleanup is a weak symbol. It is only defined if
+ * we are linked against magic */
+ if (st_do_state_cleanup)
+ r = st_do_state_cleanup();
+ if(r == OK) {
+ r = sef_cbs.sef_cb_lu_state_save(sef_lu_state, sef_lu_flags);
+ }
if(r != OK) {
- /* Abort update if callback returned error. */
+ /* Abort update in case of error. */
result = r;
}
}
/*===========================================================================*
* sef_cb_lu_state_isvalid_null *
*===========================================================================*/
-int sef_cb_lu_state_isvalid_null(int UNUSED(state))
+int sef_cb_lu_state_isvalid_null(int UNUSED(state), int UNUSED(flags))
{
return FALSE;
}
/*===========================================================================*
* sef_cb_lu_state_save_null *
*===========================================================================*/
-int sef_cb_lu_state_save_null(int UNUSED(result))
+int sef_cb_lu_state_save_null(int UNUSED(result), int UNUSED(flags))
{
return OK;
}
/*===========================================================================*
* sef_cb_lu_state_isvalid_standard *
*===========================================================================*/
-int sef_cb_lu_state_isvalid_standard(int state)
+int sef_cb_lu_state_isvalid_standard(int state, int UNUSED(flags))
{
return SEF_LU_STATE_IS_STANDARD(state);
}
/*===========================================================================*
* sef_cb_lu_state_isvalid_workfree *
*===========================================================================*/
-int sef_cb_lu_state_isvalid_workfree(int state)
+int sef_cb_lu_state_isvalid_workfree(int state, int UNUSED(flags))
{
return (state == SEF_LU_STATE_WORK_FREE);
}
+/*===========================================================================*
+ * sef_cb_lu_state_isvalid_workfree_self *
+ *===========================================================================*/
+int sef_cb_lu_state_isvalid_workfree_self(int state, int flags)
+{
+ return (state == SEF_LU_STATE_WORK_FREE) && (flags & (SEF_LU_SELF|SEF_LU_ASR));
+}
+
+/*===========================================================================*
+ * sef_cb_lu_state_isvalid_generic *
+ *===========================================================================*/
+int sef_cb_lu_state_isvalid_generic(int state, int flags)
+{
+ return (state == SEF_LU_STATE_EVAL) || sef_cb_lu_state_isvalid_workfree(state, flags);
+}
+
/*===========================================================================*
* sef_cb_lu_response_rs_reply *
*===========================================================================*/