Merge "drivers: qcom: Save authentication tag slot number to disk"
This commit is contained in:
commit
01ad9c31f5
@ -85,6 +85,10 @@ static unsigned short root_swap_dev;
|
||||
static struct work_struct save_params_work;
|
||||
static struct completion write_done;
|
||||
static unsigned char iv[IV_SIZE];
|
||||
static uint8_t *compressed_blk_array;
|
||||
static int blk_array_pos;
|
||||
static unsigned long nr_pages;
|
||||
static void *auth_slot;
|
||||
|
||||
static void init_sg(struct scatterlist *sg, void *data, unsigned int size)
|
||||
{
|
||||
@ -301,6 +305,26 @@ static int write_page(void *buf, sector_t offset, struct hib_bio_batch *hb)
|
||||
return hib_submit_io(REQ_OP_WRITE, REQ_SYNC, offset, src, hb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Number of pages compressed at one time. This is inline with UNC_PAGES
|
||||
* in kernel/power/swap.c.
|
||||
*/
|
||||
#define UNCMP_PAGES 32
|
||||
|
||||
static uint32_t get_size_of_compression_block_array(unsigned long pages)
|
||||
{
|
||||
/*
|
||||
* Get the max index based on total no. of pages. Current compression
|
||||
* algorithm compresses each UNC_PAGES pages to x pages. Use this logic to
|
||||
* get the max index.
|
||||
*/
|
||||
uint32_t max_index = DIV_ROUND_UP(pages, UNCMP_PAGES);
|
||||
|
||||
uint32_t size = ALIGN((max_index * sizeof(*compressed_blk_array)), PAGE_SIZE);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void save_auth_and_params_to_disk(struct work_struct *work)
|
||||
{
|
||||
int cur_slot;
|
||||
@ -309,7 +333,7 @@ static void save_auth_and_params_to_disk(struct work_struct *work)
|
||||
int authslot_count = 0;
|
||||
int authpage_count = read_authpage_count();
|
||||
struct hib_bio_batch hb;
|
||||
int err2;
|
||||
int err2, i = 0;
|
||||
|
||||
hib_init_batch(&hb);
|
||||
|
||||
@ -318,6 +342,27 @@ static void save_auth_and_params_to_disk(struct work_struct *work)
|
||||
*/
|
||||
params_slot = alloc_swapdev_block(root_swap_dev);
|
||||
|
||||
if (auth_slot) {
|
||||
*(int *)auth_slot = params_slot + 1;
|
||||
|
||||
/* Currently bootloader code does the following to
|
||||
* calculate the authentication slot index.
|
||||
* authslot = NrMetaPages + NrCopyPages + NrSwapMapPages +
|
||||
* HDR_SWP_INFO_NUM_PAGES;
|
||||
*
|
||||
* However, with compression enabled, we cannot apply the
|
||||
* above logic to get the authentication slot. So this
|
||||
* data should be provided to the BL for decryption to work.
|
||||
*
|
||||
* In the current implementation, BL doesn't make use of
|
||||
* the swap_map_pages for restoring the hibernation image. So these pages
|
||||
* could be used for other purposes. Use this to store the
|
||||
* authentication slot number. This data will be stored at index as
|
||||
* that of the first swap_map_page.
|
||||
*/
|
||||
write_page(auth_slot, 1, &hb);
|
||||
}
|
||||
|
||||
authpage = authslot_start;
|
||||
while (authslot_count < authpage_count) {
|
||||
cur_slot = alloc_swapdev_block(root_swap_dev);
|
||||
@ -327,6 +372,19 @@ static void save_auth_and_params_to_disk(struct work_struct *work)
|
||||
}
|
||||
params->authslot_count = authslot_count;
|
||||
write_page(params, params_slot, &hb);
|
||||
|
||||
/*
|
||||
* Write the array holding the compressed block count to disk
|
||||
*/
|
||||
if (compressed_blk_array) {
|
||||
uint32_t size = get_size_of_compression_block_array(nr_pages);
|
||||
|
||||
for (i = 0; i < size / PAGE_SIZE; i++) {
|
||||
cur_slot = alloc_swapdev_block(root_swap_dev);
|
||||
write_page(compressed_blk_array + (i * PAGE_SIZE), cur_slot, &hb);
|
||||
}
|
||||
}
|
||||
|
||||
err2 = hib_wait_io(&hb);
|
||||
hib_finish_batch(&hb);
|
||||
complete_all(&write_done);
|
||||
@ -457,6 +515,20 @@ void deinit_aes_encrypt(void)
|
||||
kfree(params);
|
||||
}
|
||||
|
||||
static void cleanup_cmp_blk_array(void)
|
||||
{
|
||||
blk_array_pos = 0;
|
||||
if (compressed_blk_array) {
|
||||
kvfree((void *)compressed_blk_array);
|
||||
compressed_blk_array = NULL;
|
||||
}
|
||||
if (auth_slot) {
|
||||
free_page((unsigned long)auth_slot);
|
||||
auth_slot = NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int hibernate_pm_notifier(struct notifier_block *nb,
|
||||
unsigned long event, void *unused)
|
||||
{
|
||||
@ -492,6 +564,7 @@ static int hibernate_pm_notifier(struct notifier_block *nb,
|
||||
|
||||
case (PM_POST_HIBERNATION):
|
||||
deinit_aes_encrypt();
|
||||
cleanup_cmp_blk_array();
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -543,6 +616,47 @@ static void init_aes_encrypt(void *data, void *unused)
|
||||
kfree(params);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bit(part of swsusp_header_flags) to indicate if the image is uncompressed
|
||||
* or not. This is inline with SF_NOCOMPRESS_MODE defined in
|
||||
* kernel/power/power.h.
|
||||
*/
|
||||
#define SF_NOCOMPRESS_MODE 2
|
||||
|
||||
static void hibernated_do_mem_alloc(void *data, unsigned long pages,
|
||||
unsigned int swsusp_header_flags, int *ret)
|
||||
{
|
||||
uint32_t size;
|
||||
|
||||
/* total no. of pages in the snapshot image */
|
||||
nr_pages = pages;
|
||||
|
||||
if (!(swsusp_header_flags & SF_NOCOMPRESS_MODE)) {
|
||||
size = get_size_of_compression_block_array(pages);
|
||||
|
||||
compressed_blk_array = kvzalloc(size, GFP_KERNEL);
|
||||
if (!compressed_blk_array) {
|
||||
*ret = -ENOMEM;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate memory to hold authentication slot start */
|
||||
auth_slot = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
if (!auth_slot) {
|
||||
pr_err("Failed to allocate page for storing authentication tag slot number\n");
|
||||
*ret = -ENOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void hibernate_save_cmp_len(void *data, size_t cmp_len)
|
||||
{
|
||||
uint8_t pages;
|
||||
|
||||
pages = DIV_ROUND_UP(cmp_len, PAGE_SIZE);
|
||||
compressed_blk_array[blk_array_pos++] = pages;
|
||||
}
|
||||
|
||||
static int __init qcom_secure_hibernattion_init(void)
|
||||
{
|
||||
int ret;
|
||||
@ -551,6 +665,8 @@ static int __init qcom_secure_hibernattion_init(void)
|
||||
register_trace_android_vh_init_aes_encrypt(init_aes_encrypt, NULL);
|
||||
register_trace_android_vh_skip_swap_map_write(skip_swap_map_write, NULL);
|
||||
register_trace_android_vh_post_image_save(save_params_to_disk, NULL);
|
||||
register_trace_android_vh_hibernate_save_cmp_len(hibernate_save_cmp_len, NULL);
|
||||
register_trace_android_vh_hibernated_do_mem_alloc(hibernated_do_mem_alloc, NULL);
|
||||
|
||||
ret = register_pm_notifier(&pm_nb);
|
||||
if (ret) {
|
||||
|
Loading…
Reference in New Issue
Block a user