cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

head-inflate-data.c (1914B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * XIP kernel .data segment decompressor
      4 *
      5 * Created by:	Nicolas Pitre, August 2017
      6 * Copyright:	(C) 2017  Linaro Limited
      7 */
      8
      9#include <linux/init.h>
     10#include <linux/zutil.h>
     11
     12/* for struct inflate_state */
     13#include "../../../lib/zlib_inflate/inftrees.h"
     14#include "../../../lib/zlib_inflate/inflate.h"
     15#include "../../../lib/zlib_inflate/infutil.h"
     16
     17extern char __data_loc[];
     18extern char _edata_loc[];
     19extern char _sdata[];
     20
     21/*
     22 * This code is called very early during the boot process to decompress
     23 * the .data segment stored compressed in ROM. Therefore none of the global
     24 * variables are valid yet, hence no kernel services such as memory
     25 * allocation is available. Everything must be allocated on the stack and
     26 * we must avoid any global data access. We use a temporary stack located
     27 * in the .bss area. The linker script makes sure the .bss is big enough
     28 * to hold our stack frame plus some room for called functions.
     29 *
     30 * We mimic the code in lib/decompress_inflate.c to use the smallest work
     31 * area possible. And because everything is statically allocated on the
     32 * stack then there is no need to clean up before returning.
     33 */
     34
     35int __init __inflate_kernel_data(void)
     36{
     37	struct z_stream_s stream, *strm = &stream;
     38	struct inflate_state state;
     39	char *in = __data_loc;
     40	int rc;
     41
     42	/* Check and skip gzip header (assume no filename) */
     43	if (in[0] != 0x1f || in[1] != 0x8b || in[2] != 0x08 || in[3] & ~3)
     44		return -1;
     45	in += 10;
     46
     47	strm->workspace = &state;
     48	strm->next_in = in;
     49	strm->avail_in = _edata_loc - __data_loc;  /* upper bound */
     50	strm->next_out = _sdata;
     51	strm->avail_out = _edata_loc - __data_loc;
     52	zlib_inflateInit2(strm, -MAX_WBITS);
     53	WS(strm)->inflate_state.wsize = 0;
     54	WS(strm)->inflate_state.window = NULL;
     55	rc = zlib_inflate(strm, Z_FINISH);
     56	if (rc == Z_OK || rc == Z_STREAM_END)
     57		rc = strm->avail_out;  /* should be 0 */
     58	return rc;
     59}