-
Notifications
You must be signed in to change notification settings - Fork 334
/
Copy pathinitrd.c
148 lines (140 loc) · 5.11 KB
/
initrd.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
* Copyright (C) 2018 bzt (bztsrc@github)
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
#include "uart.h"
// add memory compare, gcc has a built-in for that, clang needs implementation
#ifdef __clang__
int memcmp(void *s1, void *s2, int n)
{
unsigned char *a=s1,*b=s2;
while(n-->0){ if(*a!=*b) { return *a-*b; } a++; b++; }
return 0;
}
#else
#define memcmp __builtin_memcmp
#endif
/* POSIX ustar header format */
typedef struct { /* byte offset */
char name[100]; /* 0 */
char mode[8]; /* 100 */
char uid[8]; /* 108 */
char gid[8]; /* 116 */
char size[12]; /* 124 */
char mtime[12]; /* 136 */
char chksum[8]; /* 148 */
char typeflag; /* 156 */
char linkname[100]; /* 157 */
char magic[6]; /* 257 */
char version[2]; /* 263 */
char uname[32]; /* 265 */
char gname[32]; /* 297 */
char devmajor[8]; /* 329 */
char devminor[8]; /* 337 */
char prefix[167]; /* 345 */
} __attribute__((packed)) tar_t;
/* cpio hpodc format */
typedef struct {
char magic[6]; /* Magic header '070707'. */
char dev[6]; /* device number. */
char ino[6]; /* "i-node" number. */
char mode[6]; /* Permisions. */
char uid[6]; /* User ID. */
char gid[6]; /* Group ID. */
char nlink[6]; /* Number of hard links. */
char rdev[6]; /* device major/minor number. */
char mtime[11]; /* Modification time. */
char namesize[6]; /* Length of filename in bytes. */
char filesize[11]; /* File size. */
} __attribute__((packed)) cpio_t;
/**
* Helper function to convert ASCII octal number into binary
* s string
* n number of digits
*/
int oct2bin(char *s, int n)
{
int r=0;
while(n-->0) {
r<<=3;
r+=*s++-'0';
}
return r;
}
/**
* List the contents of an archive
*/
void initrd_list(char *buf)
{
char *types[]={"regular", "link ", "symlnk", "chrdev", "blkdev", "dircty", "fifo ", "??? "};
uart_puts("Type Offset Size Access rights\tFilename\n");
// iterate on archive's contents
while(!memcmp(buf+257,"ustar",5)) {
// if it's an ustar archive
tar_t *header=(tar_t*)buf;
int fs=oct2bin(header->size,11);
// print out meta information
uart_puts(types[header->typeflag-'0']);
uart_send(' ');
uart_send(' ');
uart_hex((unsigned int)((unsigned long)buf)+sizeof(tar_t));
uart_send(' ');
uart_hex(fs); // file size in hex
uart_send(' ');
uart_puts(header->mode); // access bits in octal
uart_send(' ');
uart_puts(header->uname); // owner
uart_send('.');
uart_puts(header->gname); // group
uart_send('\t');
uart_puts(buf); // filename
if(header->typeflag=='2') {
uart_puts(" -> "); // symlink target
uart_puts(header->linkname);
}
uart_puts("\n");
// jump to the next file
buf+=(((fs+511)/512)+1)*512;
}
// if it's a cpio archive. Cpio also has a trailer entry
while(!memcmp(buf,"070707",6) && memcmp(buf+sizeof(cpio_t),"TRAILER!!",9)) {
cpio_t *header = (cpio_t*)buf;
int ns=oct2bin(header->namesize,6);
int fs=oct2bin(header->filesize,11);
// print out meta information
uart_hex(oct2bin(header->mode,6)); // mode (access rights + type)
uart_send(' ');
uart_hex((unsigned int)((unsigned long)buf)+sizeof(cpio_t)+ns);
uart_send(' ');
uart_hex(fs); // file size in hex
uart_send(' ');
uart_hex(oct2bin(header->uid,6)); // user id in hex
uart_send('.');
uart_hex(oct2bin(header->gid,6)); // group id in hex
uart_send('\t');
uart_puts(buf+sizeof(cpio_t)); // filename
uart_puts("\n");
// jump to the next file
buf+=(sizeof(cpio_t)+ns+fs);
}
}