blob: b5b52b1c0803e84c4913e63589afa106687cd701 [file] [log] [blame]
#define _GNU_SOURCE
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "kexec.h"
#include "crashdump.h"
/*
* kexec_iomem_for_each_line()
*
* Iterate over each line in the file returned by proc_iomem(). If match is
* NULL or if the line matches with our match-pattern then call the
* callback if non-NULL.
* If match is NULL, callback should return a negative if error.
* Otherwise the interation goes on, incrementing nr but only if callback
* returns 0 (matched).
*
* Return the number of lines matched.
*/
int kexec_iomem_for_each_line(char *match,
int (*callback)(void *data,
int nr,
char *str,
unsigned long long base,
unsigned long long length),
void *data)
{
const char *iomem = proc_iomem();
char line[MAX_LINE];
FILE *fp;
unsigned long long start, end, size;
char *str;
int consumed;
int count;
int nr = 0, ret;
fp = fopen(iomem, "r");
if (!fp)
die("Cannot open %s\n", iomem);
while(fgets(line, sizeof(line), fp) != 0) {
count = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed);
if (count != 2)
continue;
str = line + consumed;
size = end - start + 1;
if (!match || memcmp(str, match, strlen(match)) == 0) {
if (callback) {
ret = callback(data, nr, str, start, size);
if (ret < 0)
break;
else if (ret == 0)
nr++;
}
}
}
fclose(fp);
return nr;
}
static int kexec_iomem_single_callback(void *data, int nr,
char *UNUSED(str),
unsigned long long base,
unsigned long long length)
{
struct memory_range *range = data;
if (nr == 0) {
range->start = base;
range->end = base + length - 1;
}
return 0;
}
int parse_iomem_single(char *str, uint64_t *start, uint64_t *end)
{
struct memory_range range;
int ret;
memset(&range, 0, sizeof(range));
ret = kexec_iomem_for_each_line(str,
kexec_iomem_single_callback, &range);
if (ret == 1) {
if (start)
*start = range.start;
if (end)
*end = range.end;
ret = 0;
}
else
ret = -1;
return ret;
}