mirror of
				https://review.coreboot.org/flashrom.git
				synced 2025-10-31 13:20:42 +01:00 
			
		
		
		
	tests: Add unit test to run init/shutdown for mec1308.c, ene_lpc.c
This patch includes mocks for io operations in hwaccess_x86_io.h because those are needed to test lifecycle of mec1308.c and ene_lpc.c BUG=b:181803212 TEST=builds and ninja test Change-Id: I3af612defe1af3850dfc1626a208d873e3a3eddc Signed-off-by: Anastasia Klimchuk <aklm@chromium.org> Reviewed-on: https://review.coreboot.org/c/flashrom/+/51487 Reviewed-by: Edward O'Callaghan <quasisec@chromium.org> Reviewed-by: Nico Huber <nico.h@gmx.de> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
		 Anastasia Klimchuk
					Anastasia Klimchuk
				
			
				
					committed by
					
						 Nico Huber
						Nico Huber
					
				
			
			
				
	
			
			
			 Nico Huber
						Nico Huber
					
				
			
						parent
						
							38c133438c
						
					
				
				
					commit
					21e22ba8a7
				
			
							
								
								
									
										52
									
								
								hwaccess_x86_io_unittest.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								hwaccess_x86_io_unittest.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| /* | ||||
|  * This file is part of the flashrom project. | ||||
|  * | ||||
|  * Copyright 2021 Google LLC | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; version 2 of the License. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * This header is used instead of hwaccess_x86_io.h for unit tests | ||||
|  * (see flashrom_test_dep in meson.build). | ||||
|  * | ||||
|  * There is no hardware in unit test environment and all hardware operations | ||||
|  * need to be mocked. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * The same guard is used intentionally for hwaccess_x86_io.h and | ||||
|  * hwaccess_x86_io_unittest.h. When build is made for the test environment, | ||||
|  * hwaccess_x86_io_unittest.h is included first, and it effectively | ||||
|  * replaces hwaccess_x86_io.h. | ||||
|  */ | ||||
| #ifndef __HWACCESS_X86_IO_H__ | ||||
| #define __HWACCESS_X86_IO_H__ 1 | ||||
|  | ||||
| #define OUTB(v, p) test_outb(v, p) | ||||
| #define OUTW(v, p) test_outw(v, p) | ||||
| #define OUTL(v, p) test_outl(v, p) | ||||
| #define INB(p) test_inb(p) | ||||
| #define INW(p) test_inw(p) | ||||
| #define INL(p) test_inl(p) | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include <sys/io.h> | ||||
|  | ||||
| /* All functions below are mocked in unit tests. */ | ||||
|  | ||||
| void test_outb(uint8_t value, uint16_t port); | ||||
| uint8_t test_inb(uint16_t port); | ||||
| void test_outw(uint16_t value, uint16_t port); | ||||
| uint16_t test_inw(uint16_t port); | ||||
| void test_outl(uint32_t value, uint16_t port); | ||||
| uint32_t test_inl(uint16_t port); | ||||
|  | ||||
| #endif /* !__HWACCESS_X86_IO_H__ */ | ||||
| @@ -476,6 +476,7 @@ flashrom_test_dep = declare_dependency( | ||||
|   compile_args : [ | ||||
|     '-includestdlib.h', | ||||
|     '-includeunittest_env.h', | ||||
|     '-includehwaccess_x86_io_unittest.h' | ||||
|   ], | ||||
|   dependencies : [ | ||||
|     deps, | ||||
|   | ||||
| @@ -16,6 +16,7 @@ | ||||
| #include <include/test.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "io_mock.h" | ||||
| #include "programmer.h" | ||||
|  | ||||
| static void run_lifecycle(void **state, enum programmer prog, const char *param) | ||||
| @@ -36,6 +37,105 @@ void dummy_init_and_shutdown_test_success(void **state) | ||||
| 	run_lifecycle(state, PROGRAMMER_DUMMY, "bus=parallel+lpc+fwh+spi"); | ||||
| } | ||||
|  | ||||
| struct mec1308_io_state { | ||||
| 	unsigned char outb_val; | ||||
| }; | ||||
|  | ||||
| void mec1308_outb(void *state, unsigned char value, unsigned short port) | ||||
| { | ||||
| 	struct mec1308_io_state *io_state = state; | ||||
|  | ||||
| 	io_state->outb_val = value; | ||||
| } | ||||
|  | ||||
| unsigned char mec1308_inb(void *state, unsigned short port) | ||||
| { | ||||
| 	struct mec1308_io_state *io_state = state; | ||||
|  | ||||
| 	return ((port == 0x2e /* MEC1308_SIO_PORT1 */ | ||||
| 			|| port == 0x4e /* MEC1308_SIO_PORT2 */) | ||||
| 		? 0x20 /* MEC1308_DEVICE_ID_REG */ | ||||
| 		: ((io_state->outb_val == 0x84 /* MEC1308_MBX_DATA_START */) | ||||
| 			? 0xaa /* MEC1308_CMD_PASSTHRU_SUCCESS */ | ||||
| 			: 0)); | ||||
| } | ||||
|  | ||||
| void mec1308_init_and_shutdown_test_success(void **state) | ||||
| { | ||||
| 	struct mec1308_io_state mec1308_io_state = { 0 }; | ||||
| 	const struct io_mock mec1308_io = { | ||||
| 		.state		= &mec1308_io_state, | ||||
| 		.outb		= mec1308_outb, | ||||
| 		.inb		= mec1308_inb, | ||||
| 	}; | ||||
|  | ||||
| 	io_mock_register(&mec1308_io); | ||||
|  | ||||
| 	will_return_always(__wrap_sio_read, 0x4d); /* MEC1308_DEVICE_ID_VAL */ | ||||
| 	run_lifecycle(state, PROGRAMMER_MEC1308, ""); | ||||
|  | ||||
| 	io_mock_register(NULL); | ||||
| } | ||||
|  | ||||
| struct ene_lpc_io_state { | ||||
| 	unsigned char outb_val; | ||||
| 	int pause_cmd; | ||||
| }; | ||||
|  | ||||
| void ene_lpc_outb_kb932(void *state, unsigned char value, unsigned short port) | ||||
| { | ||||
| 	struct ene_lpc_io_state *io_state = state; | ||||
|  | ||||
| 	io_state->outb_val = value; | ||||
| 	if (value == 0x59 /* ENE_KB932.ec_pause_cmd */) | ||||
| 		io_state->pause_cmd = 1; | ||||
| } | ||||
|  | ||||
| unsigned char ene_lpc_inb_kb932(void *state, unsigned short port) | ||||
| { | ||||
| 	struct ene_lpc_io_state *io_state = state; | ||||
| 	unsigned char ene_hwver_offset = 0; /* REG_EC_HWVER & 0xff */ | ||||
| 	unsigned char ene_ediid_offset = 0x24; /* REG_EC_EDIID & 0xff */ | ||||
| 	unsigned char ec_status_buf_offset = 0x54; /* ENE_KB932.ec_status_buf & 0xff */ | ||||
|  | ||||
| 	if (port == 0xfd63 /* ENE_KB932.port_io_base + port_ene_data  */) { | ||||
| 		if (io_state->outb_val == ene_hwver_offset) | ||||
| 			return 0xa2; /* ENE_KB932.hwver */ | ||||
| 		if (io_state->outb_val == ene_ediid_offset) | ||||
| 			return 0x02; /* ENE_KB932.ediid */ | ||||
| 		if (io_state->outb_val == ec_status_buf_offset) { | ||||
| 			if (io_state->pause_cmd == 1) { | ||||
| 				io_state->pause_cmd = 0; | ||||
| 				return 0x33; /* ENE_KB932.ec_is_pausing mask */ | ||||
| 			} else { | ||||
| 				return 0x00; /* ENE_KB932.ec_is_running mask */ | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void ene_lpc_init_and_shutdown_test_success(void **state) | ||||
| { | ||||
| 	/* | ||||
| 	 * Current implementation tests for chip ENE_KB932. | ||||
| 	 * Another chip which is not tested here is ENE_KB94X. | ||||
| 	 */ | ||||
| 	struct ene_lpc_io_state ene_lpc_io_state = { 0, 0 }; | ||||
| 	const struct io_mock ene_lpc_io = { | ||||
| 		.state		= &ene_lpc_io_state, | ||||
| 		.outb		= ene_lpc_outb_kb932, | ||||
| 		.inb		= ene_lpc_inb_kb932, | ||||
| 	}; | ||||
|  | ||||
| 	io_mock_register(&ene_lpc_io); | ||||
|  | ||||
| 	run_lifecycle(state, PROGRAMMER_ENE_LPC, ""); | ||||
|  | ||||
| 	io_mock_register(NULL); | ||||
| } | ||||
|  | ||||
| void linux_spi_init_and_shutdown_test_success(void **state) | ||||
| { | ||||
| 	/* | ||||
|   | ||||
| @@ -32,16 +32,16 @@ | ||||
| #define _IO_MOCK_H_ | ||||
|  | ||||
| struct io_mock { | ||||
| 	void *priv; | ||||
| 	void *state; | ||||
|  | ||||
| 	void (*outb)(void *priv, unsigned char value, unsigned short port); | ||||
| 	unsigned char (*inb)(void *priv, unsigned short port); | ||||
| 	void (*outb)(void *state, unsigned char value, unsigned short port); | ||||
| 	unsigned char (*inb)(void *state, unsigned short port); | ||||
|  | ||||
| 	void (*outw)(void *priv, unsigned short value, unsigned short port); | ||||
| 	unsigned short (*inw)(void *priv, unsigned short port); | ||||
| 	void (*outw)(void *state, unsigned short value, unsigned short port); | ||||
| 	unsigned short (*inw)(void *state, unsigned short port); | ||||
|  | ||||
| 	void (*outl)(void *priv, unsigned int value, unsigned short port); | ||||
| 	unsigned int (*inl)(void *priv, unsigned short port); | ||||
| 	void (*outl)(void *state, unsigned int value, unsigned short port); | ||||
| 	unsigned int (*inl)(void *state, unsigned short port); | ||||
| }; | ||||
|  | ||||
| void io_mock_register(const struct io_mock *io); | ||||
|   | ||||
| @@ -32,6 +32,13 @@ mocks = [ | ||||
|   '-Wl,--wrap=ioctl', | ||||
|   '-Wl,--wrap=fopen', | ||||
|   '-Wl,--wrap=fopen64', | ||||
|   '-Wl,--wrap=rget_io_perms', | ||||
|   '-Wl,--wrap=test_outb', | ||||
|   '-Wl,--wrap=test_inb', | ||||
|   '-Wl,--wrap=test_outw', | ||||
|   '-Wl,--wrap=test_inw', | ||||
|   '-Wl,--wrap=test_outl', | ||||
|   '-Wl,--wrap=test_inl', | ||||
|   '-Wl,--gc-sections', | ||||
| ] | ||||
|  | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
|  */ | ||||
|  | ||||
| #include <include/test.h> | ||||
| #include "io_mock.h" | ||||
| #include "tests.h" | ||||
|  | ||||
| #include <stdio.h> | ||||
| @@ -22,6 +23,13 @@ | ||||
| /* redefinitions/wrapping */ | ||||
| #define LOG_ME printf("%s is called\n", __func__) | ||||
|  | ||||
| static const struct io_mock *current_io = NULL; | ||||
|  | ||||
| void io_mock_register(const struct io_mock *io) | ||||
| { | ||||
| 	current_io = io; | ||||
| } | ||||
|  | ||||
| void __wrap_physunmap(void *virt_addr, size_t len) | ||||
| { | ||||
| 	LOG_ME; | ||||
| @@ -74,6 +82,51 @@ FILE *__wrap_fopen64(const char *pathname, const char *mode) | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| int __wrap_rget_io_perms(void) | ||||
| { | ||||
| 	LOG_ME; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void __wrap_test_outb(unsigned char value, unsigned short port) { | ||||
| 	/* LOG_ME; */ | ||||
| 	if (current_io && current_io->outb) | ||||
| 		current_io->outb(current_io->state, value, port); | ||||
| } | ||||
|  | ||||
| unsigned char __wrap_test_inb(unsigned short port) { | ||||
| 	/* LOG_ME; */ | ||||
| 	if (current_io && current_io->inb) | ||||
| 		return current_io->inb(current_io->state, port); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void __wrap_test_outw(unsigned short value, unsigned short port) { | ||||
| 	/* LOG_ME; */ | ||||
| 	if (current_io && current_io->outw) | ||||
| 		current_io->outw(current_io->state, value, port); | ||||
| } | ||||
|  | ||||
| unsigned short __wrap_test_inw(unsigned short port) { | ||||
| 	/* LOG_ME; */ | ||||
| 	if (current_io && current_io->inw) | ||||
| 		return current_io->inw(current_io->state, port); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void __wrap_test_outl(unsigned int value, unsigned short port) { | ||||
| 	/* LOG_ME; */ | ||||
| 	if (current_io && current_io->outl) | ||||
| 		current_io->outl(current_io->state, value, port); | ||||
| } | ||||
|  | ||||
| unsigned int __wrap_test_inl(unsigned short port) { | ||||
| 	/* LOG_ME; */ | ||||
| 	if (current_io && current_io->inl) | ||||
| 		return current_io->inl(current_io->state, port); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int main(void) | ||||
| { | ||||
| 	int ret = 0; | ||||
| @@ -112,6 +165,8 @@ int main(void) | ||||
|  | ||||
| 	const struct CMUnitTest init_shutdown_tests[] = { | ||||
| 		cmocka_unit_test(dummy_init_and_shutdown_test_success), | ||||
| 		cmocka_unit_test(mec1308_init_and_shutdown_test_success), | ||||
| 		cmocka_unit_test(ene_lpc_init_and_shutdown_test_success), | ||||
| 		cmocka_unit_test(linux_spi_init_and_shutdown_test_success), | ||||
| 	}; | ||||
| 	ret |= cmocka_run_group_tests_name("init_shutdown.c tests", init_shutdown_tests, NULL, NULL); | ||||
|   | ||||
| @@ -42,6 +42,8 @@ void probe_spi_st95_test_success(void **state); /* spi95.c */ | ||||
|  | ||||
| /* init_shutdown.c */ | ||||
| void dummy_init_and_shutdown_test_success(void **state); | ||||
| void mec1308_init_and_shutdown_test_success(void **state); | ||||
| void ene_lpc_init_and_shutdown_test_success(void **state); | ||||
| void linux_spi_init_and_shutdown_test_success(void **state); | ||||
|  | ||||
| #endif /* TESTS_H */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user