diff options
author | Robert Yang <liezhi.yang@windriver.com> | 2015-02-13 00:59:08 -0800 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-02-15 21:58:29 +0000 |
commit | a2bfd4b1fb055e63a48d80e7e55a6cff475e06d1 (patch) | |
tree | 104a6937a3153b4dbf78e6111c36be6cd213be13 | |
parent | 06ff3c420ca3b4237271879571d9933bbe6463ec (diff) | |
download | poky-a2bfd4b1fb055e63a48d80e7e55a6cff475e06d1.tar.gz |
syslinux: support ext2/3/4 device
* Support ext2/3/4 deivce.
* The open_ext2_fs() checks whether it is an ext2/3/4 device,
do the ext2/3/4 installation (install_to_ext2()) if yes, otherwise go
on to the fat/ntfs.
* The ext2/3/4 support doesn't require root privileges since it doesn't need
mount (but write permission is required).
Next:
* Get rid of fat filesystem from the boot image.
These patches have been sent to upstream, we may adjust them (maybe put
the extX support to syslinux-mtools), I will go on working with the
upstream.
(From OE-Core rev: d5af8539c0a1718a7254bcdcfa973e3c887dfbd6)
Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
10 files changed, 1345 insertions, 1 deletions
diff --git a/meta/recipes-devtools/syslinux/syslinux/0001-linux-syslinux-support-ext2-3-4-device.patch b/meta/recipes-devtools/syslinux/syslinux/0001-linux-syslinux-support-ext2-3-4-device.patch new file mode 100644 index 0000000000..3ab7875274 --- /dev/null +++ b/meta/recipes-devtools/syslinux/syslinux/0001-linux-syslinux-support-ext2-3-4-device.patch | |||
@@ -0,0 +1,84 @@ | |||
1 | From 60f3833ab2b5899771b4eab654e88f9888b99501 Mon Sep 17 00:00:00 2001 | ||
2 | From: Robert Yang <liezhi.yang@windriver.com> | ||
3 | Date: Wed, 31 Dec 2014 16:01:55 +0800 | ||
4 | Subject: [PATCH 1/9] linux/syslinux: support ext2/3/4 device | ||
5 | |||
6 | * Support ext2/3/4 deivce. | ||
7 | * The open_ext2_fs() checks whether it is an ext2/3/4 device, | ||
8 | do the ext2/3/4 installation (install_to_ext2()) if yes, otherwise go | ||
9 | on to the fat/ntfs. | ||
10 | * The ext2/3/4 support doesn't require root privileges since it doesn't need | ||
11 | mount (but write permission is required). | ||
12 | |||
13 | Upstream-Status: Submitted | ||
14 | |||
15 | Signed-off-by: Robert Yang <liezhi.yang@windriver.com> | ||
16 | Tested-by: Du Dolpher <dolpher.du@intel.com> | ||
17 | --- | ||
18 | linux/syslinux.c | 36 ++++++++++++++++++++++++++++++++++++ | ||
19 | 1 file changed, 36 insertions(+) | ||
20 | |||
21 | diff --git a/linux/syslinux.c b/linux/syslinux.c | ||
22 | index 912de71..36fc202 100755 | ||
23 | --- a/linux/syslinux.c | ||
24 | +++ b/linux/syslinux.c | ||
25 | @@ -256,6 +256,23 @@ int do_open_file(char *name) | ||
26 | return fd; | ||
27 | } | ||
28 | |||
29 | +/* | ||
30 | + * Check whether the device contains an ext2, ext3 or ext4 fs and open it if | ||
31 | + * true. | ||
32 | + * return value: | ||
33 | + * 0: Everything is OK | ||
34 | + * 1: Not an ext2, ext3 or ext4 | ||
35 | + * -1: unexpected error | ||
36 | + */ | ||
37 | +static int open_ext2_fs(const char *device, const char *subdir) | ||
38 | +{ | ||
39 | +} | ||
40 | + | ||
41 | +/* The install func for ext2, ext3 and ext4 */ | ||
42 | +static int install_to_ext2(const char *device, int dev_fd, const char *subdir) | ||
43 | +{ | ||
44 | +} | ||
45 | + | ||
46 | int main(int argc, char *argv[]) | ||
47 | { | ||
48 | static unsigned char sectbuf[SECTOR_SIZE]; | ||
49 | @@ -313,6 +330,24 @@ int main(int argc, char *argv[]) | ||
50 | die("can't combine an offset with a block device"); | ||
51 | } | ||
52 | |||
53 | + /* | ||
54 | + * Check if it is an ext2, ext3 or ext4 | ||
55 | + */ | ||
56 | + rv = open_ext2_fs(opt.device, subdir); | ||
57 | + if (rv == 0) { | ||
58 | + if (install_to_ext2(opt.device, dev_fd, subdir)) { | ||
59 | + fprintf(stderr, "%s: installation failed\n", opt.device); | ||
60 | + exit(1); | ||
61 | + } | ||
62 | + return 0; | ||
63 | + /* Unexpected errors */ | ||
64 | + } else if (rv == -1) { | ||
65 | + exit(1); | ||
66 | + } | ||
67 | + | ||
68 | + /* Reset rv */ | ||
69 | + rv = 0; | ||
70 | + | ||
71 | xpread(dev_fd, sectbuf, SECTOR_SIZE, opt.offset); | ||
72 | fsync(dev_fd); | ||
73 | |||
74 | @@ -322,6 +357,7 @@ int main(int argc, char *argv[]) | ||
75 | */ | ||
76 | if ((errmsg = syslinux_check_bootsect(sectbuf, &fs_type))) { | ||
77 | fprintf(stderr, "%s: %s\n", opt.device, errmsg); | ||
78 | + fprintf(stderr, "%s: supported fs: fat/ntfs/ext2/ex3/ext4\n", program); | ||
79 | exit(1); | ||
80 | } | ||
81 | |||
82 | -- | ||
83 | 1.9.1 | ||
84 | |||
diff --git a/meta/recipes-devtools/syslinux/syslinux/0002-linux-syslinux-implement-open_ext2_fs.patch b/meta/recipes-devtools/syslinux/syslinux/0002-linux-syslinux-implement-open_ext2_fs.patch new file mode 100644 index 0000000000..77cf060451 --- /dev/null +++ b/meta/recipes-devtools/syslinux/syslinux/0002-linux-syslinux-implement-open_ext2_fs.patch | |||
@@ -0,0 +1,141 @@ | |||
1 | From 07fb737fb60c08eaaa41989d531fc23009523546 Mon Sep 17 00:00:00 2001 | ||
2 | From: Robert Yang <liezhi.yang@windriver.com> | ||
3 | Date: Wed, 31 Dec 2014 16:09:18 +0800 | ||
4 | Subject: [PATCH 2/9] linux/syslinux: implement open_ext2_fs() | ||
5 | |||
6 | The open_ext2_fs() checks whether it is an ext2/ext3/ext4 device, and | ||
7 | return: | ||
8 | 0: It is an ext2, ext3 or ext4. | ||
9 | 1: Not an ext2, ext3 or ext4. | ||
10 | -1: unexpected error. | ||
11 | |||
12 | Upstream-Status: Submitted | ||
13 | |||
14 | Signed-off-by: Robert Yang <liezhi.yang@windriver.com> | ||
15 | Tested-by: Du Dolpher <dolpher.du@intel.com> | ||
16 | --- | ||
17 | linux/Makefile | 2 +- | ||
18 | linux/syslinux.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
19 | 2 files changed, 81 insertions(+), 1 deletion(-) | ||
20 | |||
21 | diff --git a/linux/Makefile b/linux/Makefile | ||
22 | index 11667e1..ac1ac58 100644 | ||
23 | --- a/linux/Makefile | ||
24 | +++ b/linux/Makefile | ||
25 | @@ -51,7 +51,7 @@ spotless: clean | ||
26 | installer: syslinux syslinux-nomtools | ||
27 | |||
28 | syslinux: $(OBJS) | ||
29 | - $(CC) $(LDFLAGS) -o $@ $^ | ||
30 | + $(CC) $(LDFLAGS) -o $@ $^ -lext2fs | ||
31 | |||
32 | syslinux-nomtools: syslinux | ||
33 | ln -f $< $@ | ||
34 | diff --git a/linux/syslinux.c b/linux/syslinux.c | ||
35 | index 36fc202..cc4e7da 100755 | ||
36 | --- a/linux/syslinux.c | ||
37 | +++ b/linux/syslinux.c | ||
38 | @@ -72,6 +72,7 @@ | ||
39 | #include "syslxfs.h" | ||
40 | #include "setadv.h" | ||
41 | #include "syslxopt.h" /* unified options */ | ||
42 | +#include <ext2fs/ext2fs.h> | ||
43 | |||
44 | extern const char *program; /* Name of program */ | ||
45 | |||
46 | @@ -82,6 +83,9 @@ char *mntpath = NULL; /* Path on which to mount */ | ||
47 | int loop_fd = -1; /* Loop device */ | ||
48 | #endif | ||
49 | |||
50 | +ext2_filsys e2fs = NULL; /* Ext2/3/4 filesystem */ | ||
51 | +ext2_ino_t root, cwd; /* The root and cwd of e2fs */ | ||
52 | + | ||
53 | void __attribute__ ((noreturn)) die(const char *msg) | ||
54 | { | ||
55 | fprintf(stderr, "%s: %s\n", program, msg); | ||
56 | @@ -266,6 +270,82 @@ int do_open_file(char *name) | ||
57 | */ | ||
58 | static int open_ext2_fs(const char *device, const char *subdir) | ||
59 | { | ||
60 | + int retval; | ||
61 | + int open_flag = EXT2_FLAG_RW, mount_flags; | ||
62 | + ext2_ino_t dirino; | ||
63 | + char opt_string[40]; | ||
64 | + | ||
65 | + if (opt.offset) { | ||
66 | + sprintf(opt_string, "offset=%llu", (unsigned long long)opt.offset); | ||
67 | + retval = ext2fs_open2(device, opt_string, open_flag, 0, 0, unix_io_manager, &e2fs); | ||
68 | + } else | ||
69 | + retval = ext2fs_open(device, open_flag, 0, 0, unix_io_manager, &e2fs); | ||
70 | + if (retval) { | ||
71 | + /* It might not be an extN fs, so we need check magic firstly */ | ||
72 | + if (retval == EXT2_ET_BAD_MAGIC) { | ||
73 | + /* Do nothing, return silently */ | ||
74 | + return 1; | ||
75 | + } else { | ||
76 | + fprintf(stderr, "%s: error while trying to open: %s\n", | ||
77 | + program, device); | ||
78 | + return -1; | ||
79 | + } | ||
80 | + } | ||
81 | + | ||
82 | + /* Stop if it is mounted */ | ||
83 | + retval = ext2fs_check_if_mounted(device, &mount_flags); | ||
84 | + if (retval) { | ||
85 | + fprintf(stderr, "%s: ext2fs_check_if_mount() error on %s\n", | ||
86 | + program, device); | ||
87 | + goto fail; | ||
88 | + } | ||
89 | + | ||
90 | + if (mount_flags & EXT2_MF_MOUNTED) { | ||
91 | + fprintf(stderr, "%s: %s is mounted\n", program, device); | ||
92 | + goto fail; | ||
93 | + } | ||
94 | + | ||
95 | + e2fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE; | ||
96 | + | ||
97 | + /* Read the inode map */ | ||
98 | + retval = ext2fs_read_inode_bitmap(e2fs); | ||
99 | + if (retval) { | ||
100 | + fprintf(stderr, "%s: while reading inode bitmap: %s\n", | ||
101 | + program, device); | ||
102 | + goto fail; | ||
103 | + } | ||
104 | + | ||
105 | + /* Read the block map */ | ||
106 | + retval = ext2fs_read_block_bitmap(e2fs); | ||
107 | + if (retval) { | ||
108 | + fprintf(stderr, "%s: while reading block bitmap: %s\n", | ||
109 | + program, device); | ||
110 | + goto fail; | ||
111 | + } | ||
112 | + | ||
113 | + root = cwd = EXT2_ROOT_INO; | ||
114 | + /* Check the subdir */ | ||
115 | + if (strcmp(subdir, "/")) { | ||
116 | + retval = ext2fs_namei(e2fs, root, cwd, subdir, &dirino); | ||
117 | + if (retval) { | ||
118 | + fprintf(stderr, "%s: failed to find dir %s on %s\n", | ||
119 | + program, subdir, device); | ||
120 | + goto fail; | ||
121 | + } | ||
122 | + | ||
123 | + retval = ext2fs_check_directory(e2fs, dirino); | ||
124 | + if (retval) { | ||
125 | + fprintf(stderr, "%s: failed to cd to: %s\n", program, subdir); | ||
126 | + goto fail; | ||
127 | + } | ||
128 | + cwd = dirino; | ||
129 | + } | ||
130 | + | ||
131 | + return 0; | ||
132 | + | ||
133 | +fail: | ||
134 | + (void) ext2fs_close(e2fs); | ||
135 | + return -1; | ||
136 | } | ||
137 | |||
138 | /* The install func for ext2, ext3 and ext4 */ | ||
139 | -- | ||
140 | 1.9.1 | ||
141 | |||
diff --git a/meta/recipes-devtools/syslinux/syslinux/0003-linux-syslinux-implement-install_to_ext2.patch b/meta/recipes-devtools/syslinux/syslinux/0003-linux-syslinux-implement-install_to_ext2.patch new file mode 100644 index 0000000000..84ba10526a --- /dev/null +++ b/meta/recipes-devtools/syslinux/syslinux/0003-linux-syslinux-implement-install_to_ext2.patch | |||
@@ -0,0 +1,116 @@ | |||
1 | From 64d856b243812907068776b204a003a3a8fa122a Mon Sep 17 00:00:00 2001 | ||
2 | From: Robert Yang <liezhi.yang@windriver.com> | ||
3 | Date: Wed, 31 Dec 2014 16:17:42 +0800 | ||
4 | Subject: [PATCH 3/9] linux/syslinux: implement install_to_ext2() | ||
5 | |||
6 | * The handle_adv_on_ext() checks whether we only need update adv. | ||
7 | * The write_to_ext() installs files (ldlinux.sys or ldlinux.c32) to the | ||
8 | device. | ||
9 | * The install_bootblock() installs the boot block. | ||
10 | |||
11 | Upstream-Status: Submitted | ||
12 | |||
13 | Signed-off-by: Robert Yang <liezhi.yang@windriver.com> | ||
14 | Tested-by: Du Dolpher <dolpher.du@intel.com> | ||
15 | --- | ||
16 | linux/syslinux.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
17 | 1 file changed, 79 insertions(+) | ||
18 | |||
19 | diff --git a/linux/syslinux.c b/linux/syslinux.c | ||
20 | index cc4e7da..45f080d 100755 | ||
21 | --- a/linux/syslinux.c | ||
22 | +++ b/linux/syslinux.c | ||
23 | @@ -346,11 +346,90 @@ static int open_ext2_fs(const char *device, const char *subdir) | ||
24 | fail: | ||
25 | (void) ext2fs_close(e2fs); | ||
26 | return -1; | ||
27 | + | ||
28 | +} | ||
29 | + | ||
30 | +/* | ||
31 | + * Install the boot block on the specified device. | ||
32 | + * Must be run AFTER file installed. | ||
33 | + */ | ||
34 | +int install_bootblock(int fd, const char *device) | ||
35 | +{ | ||
36 | +} | ||
37 | + | ||
38 | +static int handle_adv_on_ext(void) | ||
39 | +{ | ||
40 | +} | ||
41 | + | ||
42 | +/* Write files, adv, boot sector */ | ||
43 | +static int write_to_ext(const char *filename, const char *str, int length, | ||
44 | + int i_flags, int dev_fd, const char *subdir) | ||
45 | +{ | ||
46 | } | ||
47 | |||
48 | /* The install func for ext2, ext3 and ext4 */ | ||
49 | static int install_to_ext2(const char *device, int dev_fd, const char *subdir) | ||
50 | { | ||
51 | + int retval; | ||
52 | + ext2_ino_t oldino; | ||
53 | + | ||
54 | + const char *file = "ldlinux.sys"; | ||
55 | + const char *oldfile = "extlinux.sys"; | ||
56 | + const char *c32file = "ldlinux.c32"; | ||
57 | + | ||
58 | + /* Handle the adv */ | ||
59 | + if (handle_adv_on_ext() < 0) { | ||
60 | + fprintf(stderr, "%s: error while handling ADV on %s\n", | ||
61 | + program, device); | ||
62 | + retval = 1; | ||
63 | + goto fail; | ||
64 | + } | ||
65 | + | ||
66 | + /* Return if only need update the adv */ | ||
67 | + if (opt.update_only == -1) { | ||
68 | + return ext2fs_close(e2fs); | ||
69 | + } | ||
70 | + | ||
71 | + /* Write ldlinux.sys, adv, boot sector */ | ||
72 | + retval = write_to_ext(file, (const char _force *)boot_image, | ||
73 | + boot_image_len, EXT2_IMMUTABLE_FL, dev_fd, subdir); | ||
74 | + if (retval) { | ||
75 | + fprintf(stderr, "%s: ERROR: while writing: %s.\n", | ||
76 | + program, file); | ||
77 | + goto fail; | ||
78 | + } | ||
79 | + | ||
80 | + /* Write ldlinux.c32 */ | ||
81 | + retval = write_to_ext(c32file, | ||
82 | + (const char _force *)syslinux_ldlinuxc32, | ||
83 | + syslinux_ldlinuxc32_len, 0, dev_fd, subdir); | ||
84 | + if (retval) { | ||
85 | + fprintf(stderr, "%s: ERROR: while writing: %s.\n", | ||
86 | + program, c32file); | ||
87 | + goto fail; | ||
88 | + } | ||
89 | + | ||
90 | + /* Look if we have the extlinux.sys and remove it*/ | ||
91 | + retval = ext2fs_namei(e2fs, root, cwd, oldfile, &oldino); | ||
92 | + if (retval == 0) { | ||
93 | + retval = ext2fs_unlink(e2fs, cwd, oldfile, oldino, 0); | ||
94 | + if (retval) { | ||
95 | + fprintf(stderr, "%s: ERROR: failed to unlink: %s\n", | ||
96 | + program, oldfile); | ||
97 | + goto fail; | ||
98 | + } | ||
99 | + } else { | ||
100 | + retval = 0; | ||
101 | + } | ||
102 | + | ||
103 | + sync(); | ||
104 | + retval = install_bootblock(dev_fd, device); | ||
105 | + close(dev_fd); | ||
106 | + sync(); | ||
107 | + | ||
108 | +fail: | ||
109 | + (void) ext2fs_close(e2fs); | ||
110 | + return retval; | ||
111 | } | ||
112 | |||
113 | int main(int argc, char *argv[]) | ||
114 | -- | ||
115 | 1.9.1 | ||
116 | |||
diff --git a/meta/recipes-devtools/syslinux/syslinux/0004-linux-syslinux-add-ext_file_read-and-ext_file_write.patch b/meta/recipes-devtools/syslinux/syslinux/0004-linux-syslinux-add-ext_file_read-and-ext_file_write.patch new file mode 100644 index 0000000000..64b56d92e0 --- /dev/null +++ b/meta/recipes-devtools/syslinux/syslinux/0004-linux-syslinux-add-ext_file_read-and-ext_file_write.patch | |||
@@ -0,0 +1,91 @@ | |||
1 | From 35d3842cc4b930c5102eed2921e0189b7f4fd069 Mon Sep 17 00:00:00 2001 | ||
2 | From: Robert Yang <liezhi.yang@windriver.com> | ||
3 | Date: Wed, 31 Dec 2014 16:43:37 +0800 | ||
4 | Subject: [PATCH 4/9] linux/syslinux: add ext_file_read() and ext_file_write() | ||
5 | |||
6 | Will use them to read and write on the extX device. | ||
7 | |||
8 | Upstream-Status: Submitted | ||
9 | |||
10 | Signed-off-by: Robert Yang <liezhi.yang@windriver.com> | ||
11 | Tested-by: Du Dolpher <dolpher.du@intel.com> | ||
12 | --- | ||
13 | linux/syslinux.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
14 | 1 file changed, 62 insertions(+) | ||
15 | |||
16 | diff --git a/linux/syslinux.c b/linux/syslinux.c | ||
17 | index 45f080d..247c86a 100755 | ||
18 | --- a/linux/syslinux.c | ||
19 | +++ b/linux/syslinux.c | ||
20 | @@ -349,6 +349,68 @@ fail: | ||
21 | |||
22 | } | ||
23 | |||
24 | +/* Read from an ext2_file */ | ||
25 | +static int ext_file_read(ext2_file_t e2_file, void *buf, size_t count, | ||
26 | + off_t offset, const char *msg) | ||
27 | +{ | ||
28 | + int retval; | ||
29 | + char *ptr = (char *) buf; | ||
30 | + unsigned int got = 0; | ||
31 | + size_t done = 0; | ||
32 | + | ||
33 | + /* Always lseek since e2_file is uncontrolled by this func */ | ||
34 | + if (ext2fs_file_lseek(e2_file, offset, EXT2_SEEK_SET, NULL)) { | ||
35 | + fprintf(stderr, "%s: ext2fs_file_lseek() failed.\n", | ||
36 | + program); | ||
37 | + return -1; | ||
38 | + } | ||
39 | + | ||
40 | + while (1) { | ||
41 | + retval = ext2fs_file_read(e2_file, ptr, count, &got); | ||
42 | + if (retval) { | ||
43 | + fprintf(stderr, "%s: error while reading %s\n", | ||
44 | + program, msg); | ||
45 | + return -1; | ||
46 | + } | ||
47 | + count -= got; | ||
48 | + ptr += got; | ||
49 | + done += got; | ||
50 | + if (got == 0 || count == 0) | ||
51 | + break; | ||
52 | + } | ||
53 | + | ||
54 | + return done; | ||
55 | +} | ||
56 | + | ||
57 | +/* Write to an ext2_file */ | ||
58 | +static int ext_file_write(ext2_file_t e2_file, const void *buf, size_t count, | ||
59 | + off_t offset) | ||
60 | +{ | ||
61 | + const char *ptr = (const char *) buf; | ||
62 | + unsigned int written = 0; | ||
63 | + size_t done = 0; | ||
64 | + | ||
65 | + /* Always lseek since e2_file is uncontrolled by this func */ | ||
66 | + if (ext2fs_file_lseek(e2_file, offset, EXT2_SEEK_SET, NULL)) { | ||
67 | + fprintf(stderr, "%s: ext2fs_file_lseek() failed.\n", | ||
68 | + program); | ||
69 | + return -1; | ||
70 | + } | ||
71 | + | ||
72 | + while (count > 0) { | ||
73 | + if (ext2fs_file_write(e2_file, ptr, count, &written)) { | ||
74 | + fprintf(stderr, "%s: failed to write syslinux adv.\n", | ||
75 | + program); | ||
76 | + return -1; | ||
77 | + } | ||
78 | + count -= written; | ||
79 | + ptr += written; | ||
80 | + done += written; | ||
81 | + } | ||
82 | + | ||
83 | + return done; | ||
84 | +} | ||
85 | + | ||
86 | /* | ||
87 | * Install the boot block on the specified device. | ||
88 | * Must be run AFTER file installed. | ||
89 | -- | ||
90 | 1.9.1 | ||
91 | |||
diff --git a/meta/recipes-devtools/syslinux/syslinux/0005-linux-syslinux-implement-handle_adv_on_ext.patch b/meta/recipes-devtools/syslinux/syslinux/0005-linux-syslinux-implement-handle_adv_on_ext.patch new file mode 100644 index 0000000000..829e7c4ca1 --- /dev/null +++ b/meta/recipes-devtools/syslinux/syslinux/0005-linux-syslinux-implement-handle_adv_on_ext.patch | |||
@@ -0,0 +1,127 @@ | |||
1 | From cdb980b37f40dc2c41891434c7736e49da53756e Mon Sep 17 00:00:00 2001 | ||
2 | From: Robert Yang <liezhi.yang@windriver.com> | ||
3 | Date: Wed, 31 Dec 2014 16:47:52 +0800 | ||
4 | Subject: [PATCH 5/9] linux/syslinux: implement handle_adv_on_ext() | ||
5 | |||
6 | It reads adv if found on the device, or resets syslinux_adv, or update | ||
7 | the adv if update adv only. | ||
8 | |||
9 | Upstream-Status: Submitted | ||
10 | |||
11 | Signed-off-by: Robert Yang <liezhi.yang@windriver.com> | ||
12 | Tested-by: Du Dolpher <dolpher.du@intel.com> | ||
13 | --- | ||
14 | linux/syslinux.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
15 | 1 file changed, 97 insertions(+) | ||
16 | |||
17 | diff --git a/linux/syslinux.c b/linux/syslinux.c | ||
18 | index 247c86a..de5d272 100755 | ||
19 | --- a/linux/syslinux.c | ||
20 | +++ b/linux/syslinux.c | ||
21 | @@ -421,6 +421,103 @@ int install_bootblock(int fd, const char *device) | ||
22 | |||
23 | static int handle_adv_on_ext(void) | ||
24 | { | ||
25 | + int i, retval, found_file; | ||
26 | + int need_close = 2; /* 2 means no need extra close */ | ||
27 | + char *filenames[2] = {"ldlinux.sys", "extlinux.sys"}; | ||
28 | + char *filename; | ||
29 | + ext2_ino_t newino; | ||
30 | + ext2_file_t e2_file; | ||
31 | + struct ext2_inode inode; | ||
32 | + | ||
33 | + for (i = 0; i < 2; i++) { | ||
34 | + filename = filenames[i]; | ||
35 | + found_file = 0; | ||
36 | + retval = ext2fs_namei(e2fs, root, cwd, filename, &newino); | ||
37 | + if (retval == 0) { | ||
38 | + found_file = 1; | ||
39 | + } else | ||
40 | + continue; | ||
41 | + | ||
42 | + need_close = i; | ||
43 | + | ||
44 | + retval = ext2fs_file_open(e2fs, newino, EXT2_FLAG_RW, &e2_file); | ||
45 | + if (retval) { | ||
46 | + fprintf(stderr, "%s: failed to open %s\n", | ||
47 | + program, filename); | ||
48 | + goto fail; | ||
49 | + } | ||
50 | + | ||
51 | + retval = ext2fs_read_inode(e2fs, newino, &inode); | ||
52 | + if (retval) { | ||
53 | + fprintf(stderr, "%s: error while reading inode: %u, file: %s\n", | ||
54 | + program, newino, filename); | ||
55 | + goto fail; | ||
56 | + } | ||
57 | + | ||
58 | + /* Check the size to see if too small to read */ | ||
59 | + if (inode.i_size < 2 * ADV_SIZE) { | ||
60 | + if (opt.update_only == -1) { | ||
61 | + fprintf(stderr, "%s: failed to write auxilliary data\n\ | ||
62 | + the size of %s is too small (need --update)?\n", | ||
63 | + program, filename); | ||
64 | + retval = -1; | ||
65 | + goto fail; | ||
66 | + } | ||
67 | + syslinux_reset_adv(syslinux_adv); | ||
68 | + found_file = 0; | ||
69 | + break; | ||
70 | + } | ||
71 | + | ||
72 | + /* Read the adv */ | ||
73 | + retval = ext_file_read(e2_file, syslinux_adv, 2 * ADV_SIZE, | ||
74 | + inode.i_size - 2 * ADV_SIZE, "ADV"); | ||
75 | + if (retval == -1) | ||
76 | + goto fail; | ||
77 | + if (retval == 2 * ADV_SIZE) { | ||
78 | + retval = syslinux_validate_adv(syslinux_adv); | ||
79 | + /* Read the adv successfully */ | ||
80 | + if (retval == 0) | ||
81 | + break; | ||
82 | + } | ||
83 | + | ||
84 | + /* Close the file if reaches here, otherwise we leave the file | ||
85 | + * open in case we need write it */ | ||
86 | + need_close = 2; | ||
87 | + retval = ext2fs_file_close(e2_file); | ||
88 | + if (retval) { | ||
89 | + fprintf(stderr, "%s: error while closing %s\n", | ||
90 | + program, filename); | ||
91 | + return retval; | ||
92 | + } | ||
93 | + } | ||
94 | + | ||
95 | + if (!found_file) { | ||
96 | + if (opt.update_only == -1) { | ||
97 | + fprintf(stderr, "%s: no ldlinux.sys or extlinux.sys found on the device\n", | ||
98 | + program); | ||
99 | + return -1; | ||
100 | + } | ||
101 | + syslinux_reset_adv(syslinux_adv); | ||
102 | + } | ||
103 | + | ||
104 | + /* The modify_adv will reset the adv if opt.reset_adv */ | ||
105 | + if (modify_adv() < 0) { | ||
106 | + fprintf(stderr, "%s: error while modifying adv\n", program); | ||
107 | + retval = -1; | ||
108 | + goto fail; | ||
109 | + } | ||
110 | + | ||
111 | + /* Write adv if update_only == -1 and found file */ | ||
112 | + if (opt.update_only == -1 && found_file) { | ||
113 | + if (ext_file_write(e2_file, syslinux_adv, 2 * ADV_SIZE , | ||
114 | + inode.i_size - 2 * ADV_SIZE) == -1) | ||
115 | + goto fail; | ||
116 | + } | ||
117 | + | ||
118 | +fail: | ||
119 | + if (need_close != 2) | ||
120 | + (void) ext2fs_file_close(e2_file); | ||
121 | + return retval; | ||
122 | } | ||
123 | |||
124 | /* Write files, adv, boot sector */ | ||
125 | -- | ||
126 | 1.9.1 | ||
127 | |||
diff --git a/meta/recipes-devtools/syslinux/syslinux/0006-linux-syslinux-implement-write_to_ext-and-add-syslin.patch b/meta/recipes-devtools/syslinux/syslinux/0006-linux-syslinux-implement-write_to_ext-and-add-syslin.patch new file mode 100644 index 0000000000..cba87252a5 --- /dev/null +++ b/meta/recipes-devtools/syslinux/syslinux/0006-linux-syslinux-implement-write_to_ext-and-add-syslin.patch | |||
@@ -0,0 +1,215 @@ | |||
1 | From 922e56c10e36d876777580c84daef9a66bea6525 Mon Sep 17 00:00:00 2001 | ||
2 | From: Robert Yang <liezhi.yang@windriver.com> | ||
3 | Date: Wed, 31 Dec 2014 17:20:43 +0800 | ||
4 | Subject: [PATCH 6/9] linux/syslinux: implement write_to_ext() and add | ||
5 | syslinuxext.c | ||
6 | |||
7 | * The write_to_ext() write file to the extX device, and handle the boot | ||
8 | sector. | ||
9 | * The syslinuxext.c is used for placing the code which are used by | ||
10 | extlinux and syslinux (which is syslinux_patch_bootsect()). | ||
11 | |||
12 | Upstream-Status: Submitted | ||
13 | |||
14 | Signed-off-by: Robert Yang <liezhi.yang@windriver.com> | ||
15 | Tested-by: Du Dolpher <dolpher.du@intel.com> | ||
16 | --- | ||
17 | libinstaller/syslinuxext.c | 7 +++ | ||
18 | libinstaller/syslinuxext.h | 5 ++ | ||
19 | linux/Makefile | 3 +- | ||
20 | linux/syslinux.c | 118 +++++++++++++++++++++++++++++++++++++++++++++ | ||
21 | 4 files changed, 132 insertions(+), 1 deletion(-) | ||
22 | create mode 100644 libinstaller/syslinuxext.c | ||
23 | create mode 100644 libinstaller/syslinuxext.h | ||
24 | |||
25 | diff --git a/libinstaller/syslinuxext.c b/libinstaller/syslinuxext.c | ||
26 | new file mode 100644 | ||
27 | index 0000000..bb54cef | ||
28 | --- /dev/null | ||
29 | +++ b/libinstaller/syslinuxext.c | ||
30 | @@ -0,0 +1,7 @@ | ||
31 | +#define _GNU_SOURCE | ||
32 | + | ||
33 | +/* Patch syslinux_bootsect */ | ||
34 | +void syslinux_patch_bootsect(int dev_fd) | ||
35 | +{ | ||
36 | +} | ||
37 | + | ||
38 | diff --git a/libinstaller/syslinuxext.h b/libinstaller/syslinuxext.h | ||
39 | new file mode 100644 | ||
40 | index 0000000..8abd8b9 | ||
41 | --- /dev/null | ||
42 | +++ b/libinstaller/syslinuxext.h | ||
43 | @@ -0,0 +1,5 @@ | ||
44 | +#ifndef EXT2_SUPER_OFFSET | ||
45 | +#define EXT2_SUPER_OFFSET 1024 | ||
46 | +#endif | ||
47 | + | ||
48 | +void syslinux_patch_bootsect(int dev_fd); | ||
49 | diff --git a/linux/Makefile b/linux/Makefile | ||
50 | index ac1ac58..3b23867 100644 | ||
51 | --- a/linux/Makefile | ||
52 | +++ b/linux/Makefile | ||
53 | @@ -30,7 +30,8 @@ SRCS = syslinux.c \ | ||
54 | ../libinstaller/syslxmod.c \ | ||
55 | ../libinstaller/bootsect_bin.c \ | ||
56 | ../libinstaller/ldlinuxc32_bin.c \ | ||
57 | - ../libinstaller/ldlinux_bin.c | ||
58 | + ../libinstaller/ldlinux_bin.c \ | ||
59 | + ../libinstaller/syslinuxext.c | ||
60 | OBJS = $(patsubst %.c,%.o,$(notdir $(SRCS))) | ||
61 | |||
62 | .SUFFIXES: .c .o .i .s .S | ||
63 | diff --git a/linux/syslinux.c b/linux/syslinux.c | ||
64 | index de5d272..f0c97a8 100755 | ||
65 | --- a/linux/syslinux.c | ||
66 | +++ b/linux/syslinux.c | ||
67 | @@ -46,6 +46,7 @@ | ||
68 | #include <sys/types.h> | ||
69 | #include <sys/wait.h> | ||
70 | #include <sys/mount.h> | ||
71 | +#include <time.h> | ||
72 | |||
73 | #include "linuxioctl.h" | ||
74 | |||
75 | @@ -72,6 +73,7 @@ | ||
76 | #include "syslxfs.h" | ||
77 | #include "setadv.h" | ||
78 | #include "syslxopt.h" /* unified options */ | ||
79 | +#include "syslinuxext.h" | ||
80 | #include <ext2fs/ext2fs.h> | ||
81 | |||
82 | extern const char *program; /* Name of program */ | ||
83 | @@ -419,6 +421,12 @@ int install_bootblock(int fd, const char *device) | ||
84 | { | ||
85 | } | ||
86 | |||
87 | +/* Construct the boot file map */ | ||
88 | +int ext_construct_sectmap_fs(ext2_filsys fs, ext2_ino_t newino, | ||
89 | + sector_t *sectors, int nsect) | ||
90 | +{ | ||
91 | +} | ||
92 | + | ||
93 | static int handle_adv_on_ext(void) | ||
94 | { | ||
95 | int i, retval, found_file; | ||
96 | @@ -524,6 +532,116 @@ fail: | ||
97 | static int write_to_ext(const char *filename, const char *str, int length, | ||
98 | int i_flags, int dev_fd, const char *subdir) | ||
99 | { | ||
100 | + ext2_ino_t newino; | ||
101 | + struct ext2_inode inode; | ||
102 | + int retval, i, modbytes, nsect; | ||
103 | + ext2_file_t e2_file; | ||
104 | + sector_t *sectors; | ||
105 | + | ||
106 | + /* Remove it if it is already exists */ | ||
107 | + retval = ext2fs_namei(e2fs, root, cwd, filename, &newino); | ||
108 | + if (retval == 0) { | ||
109 | + retval = ext2fs_unlink(e2fs, cwd, filename, newino, 0); | ||
110 | + if (retval) { | ||
111 | + fprintf(stderr, "%s: failed to unlink: %s\n", program, filename); | ||
112 | + return retval; | ||
113 | + } | ||
114 | + } | ||
115 | + | ||
116 | + /* Create new inode */ | ||
117 | + retval = ext2fs_new_inode(e2fs, cwd, 010755, 0, &newino); | ||
118 | + if (retval) { | ||
119 | + fprintf(stderr, "%s: ERROR: failed to create inode for: %s\n", | ||
120 | + program, filename); | ||
121 | + return retval; | ||
122 | + } | ||
123 | + | ||
124 | + /* Link the inode and the filename */ | ||
125 | + retval = ext2fs_link(e2fs, cwd, filename, newino, EXT2_FT_REG_FILE); | ||
126 | + if (retval) { | ||
127 | + fprintf(stderr, "%s: ERROR: failed to link inode for: %s.\n", | ||
128 | + program, filename); | ||
129 | + return retval; | ||
130 | + } | ||
131 | + | ||
132 | + if (ext2fs_test_inode_bitmap2(e2fs->inode_map, newino)) | ||
133 | + fprintf(stderr, "%s: warning: inode already set %s.\n", | ||
134 | + program, filename); | ||
135 | + | ||
136 | + ext2fs_inode_alloc_stats2(e2fs, newino, +1, 0); | ||
137 | + memset(&inode, 0, sizeof(inode)); | ||
138 | + inode.i_mode = LINUX_S_IFREG | LINUX_S_IRUSR | LINUX_S_IRGRP | ||
139 | + | LINUX_S_IROTH; | ||
140 | + inode.i_flags |= i_flags; | ||
141 | + inode.i_atime = inode.i_ctime = inode.i_mtime = | ||
142 | + e2fs->now ? e2fs->now : time(0); | ||
143 | + inode.i_links_count = 1; | ||
144 | + if (e2fs->super->s_feature_incompat & | ||
145 | + EXT3_FEATURE_INCOMPAT_EXTENTS) { | ||
146 | + struct ext3_extent_header *eh; | ||
147 | + | ||
148 | + eh = (struct ext3_extent_header *) &inode.i_block[0]; | ||
149 | + eh->eh_depth = 0; | ||
150 | + eh->eh_entries = 0; | ||
151 | + eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC); | ||
152 | + i = (sizeof(inode.i_block) - sizeof(*eh)) / | ||
153 | + sizeof(struct ext3_extent); | ||
154 | + eh->eh_max = ext2fs_cpu_to_le16(i); | ||
155 | + inode.i_flags |= EXT4_EXTENTS_FL; | ||
156 | + } | ||
157 | + | ||
158 | + retval = ext2fs_write_new_inode(e2fs, newino, &inode); | ||
159 | + if (retval) { | ||
160 | + fprintf(stderr, "%s: ERROR: while writting inode %d.\n", | ||
161 | + program, newino); | ||
162 | + return 1; | ||
163 | + } | ||
164 | + | ||
165 | + retval = ext2fs_file_open(e2fs, newino, EXT2_FILE_WRITE, &e2_file); | ||
166 | + if (retval) { | ||
167 | + fprintf(stderr, "%s: ERROR: failed to open %s.\n", | ||
168 | + program, filename); | ||
169 | + return 1; | ||
170 | + } | ||
171 | + | ||
172 | + /* Write to file */ | ||
173 | + if (ext_file_write(e2_file, str, length, 0) == -1) | ||
174 | + goto fail; | ||
175 | + | ||
176 | + if (strcmp(filename, "ldlinux.sys") == 0) { | ||
177 | + /* Write ADV */ | ||
178 | + if (ext_file_write(e2_file, syslinux_adv, 2 * ADV_SIZE, | ||
179 | + boot_image_len) == -1) | ||
180 | + goto fail; | ||
181 | + | ||
182 | + /* Patch syslinux_bootsect */ | ||
183 | + syslinux_patch_bootsect(dev_fd); | ||
184 | + | ||
185 | + /* Patch ldlinux.sys */ | ||
186 | + nsect = (boot_image_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT; | ||
187 | + nsect += 2; /* Two sectors for the ADV */ | ||
188 | + sectors = alloca(sizeof(sector_t) * nsect); | ||
189 | + memset(sectors, 0, nsect * sizeof *sectors); | ||
190 | + /* The sectors will be modified and used by syslinux_patch() */ | ||
191 | + retval = ext_construct_sectmap_fs(e2fs, newino, sectors, nsect); | ||
192 | + if (retval) | ||
193 | + goto fail; | ||
194 | + | ||
195 | + /* Create the modified image in memory */ | ||
196 | + modbytes = syslinux_patch(sectors, nsect, opt.stupid_mode, | ||
197 | + opt.raid_mode, subdir, NULL); | ||
198 | + | ||
199 | + /* Rewrite the first modbytes of ldlinux.sys */ | ||
200 | + if (ext_file_write(e2_file, str, modbytes, 0) == -1) { | ||
201 | + fprintf(stderr, "%s: ERROR: failed to patch %s.\n", program, | ||
202 | + filename); | ||
203 | + goto fail; | ||
204 | + } | ||
205 | + } | ||
206 | + | ||
207 | +fail: | ||
208 | + (void) ext2fs_file_close(e2_file); | ||
209 | + return retval; | ||
210 | } | ||
211 | |||
212 | /* The install func for ext2, ext3 and ext4 */ | ||
213 | -- | ||
214 | 1.9.1 | ||
215 | |||
diff --git a/meta/recipes-devtools/syslinux/syslinux/0007-linux-syslinux-implement-ext_construct_sectmap_fs.patch b/meta/recipes-devtools/syslinux/syslinux/0007-linux-syslinux-implement-ext_construct_sectmap_fs.patch new file mode 100644 index 0000000000..3913811917 --- /dev/null +++ b/meta/recipes-devtools/syslinux/syslinux/0007-linux-syslinux-implement-ext_construct_sectmap_fs.patch | |||
@@ -0,0 +1,84 @@ | |||
1 | From a95b831e18dd123f859bc5e6c4cecdcc0184ee37 Mon Sep 17 00:00:00 2001 | ||
2 | From: Robert Yang <liezhi.yang@windriver.com> | ||
3 | Date: Fri, 2 Jan 2015 12:18:02 +0800 | ||
4 | Subject: [PATCH 7/9] linux/syslinux: implement ext_construct_sectmap_fs() | ||
5 | |||
6 | The ext_construct_sectmap_fs() constucts the sector according to the | ||
7 | bmap. | ||
8 | |||
9 | Upstream-Status: Submitted | ||
10 | |||
11 | Signed-off-by: Robert Yang <liezhi.yang@windriver.com> | ||
12 | Tested-by: Du Dolpher <dolpher.du@intel.com> | ||
13 | --- | ||
14 | linux/syslinux.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
15 | 1 file changed, 50 insertions(+) | ||
16 | |||
17 | diff --git a/linux/syslinux.c b/linux/syslinux.c | ||
18 | index f0c97a8..c741750 100755 | ||
19 | --- a/linux/syslinux.c | ||
20 | +++ b/linux/syslinux.c | ||
21 | @@ -421,10 +421,60 @@ int install_bootblock(int fd, const char *device) | ||
22 | { | ||
23 | } | ||
24 | |||
25 | +/* The file's block count */ | ||
26 | +int block_count = 0; | ||
27 | +static int get_block_count(ext2_filsys fs EXT2FS_ATTR((unused)), | ||
28 | + blk64_t *blocknr EXT2FS_ATTR((unused)), | ||
29 | + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), | ||
30 | + blk64_t ref_block EXT2FS_ATTR((unused)), | ||
31 | + int ref_offset EXT2FS_ATTR((unused)), | ||
32 | + void *private EXT2FS_ATTR((unused))) | ||
33 | +{ | ||
34 | + block_count++; | ||
35 | + return 0; | ||
36 | +} | ||
37 | + | ||
38 | /* Construct the boot file map */ | ||
39 | int ext_construct_sectmap_fs(ext2_filsys fs, ext2_ino_t newino, | ||
40 | sector_t *sectors, int nsect) | ||
41 | { | ||
42 | + blk64_t pblk, blksize, blk = 0; | ||
43 | + sector_t sec; | ||
44 | + unsigned int i; | ||
45 | + int retval; | ||
46 | + | ||
47 | + blksize = fs->blocksize; | ||
48 | + blksize >>= SECTOR_SHIFT; | ||
49 | + | ||
50 | + /* Get the total blocks no. */ | ||
51 | + retval = ext2fs_block_iterate3(fs, newino, BLOCK_FLAG_READ_ONLY, | ||
52 | + NULL, get_block_count, NULL); | ||
53 | + if (retval) { | ||
54 | + fprintf(stderr, "%s: ERROR: ext2fs_block_iterate3() failed.\n", program); | ||
55 | + return -1; | ||
56 | + } | ||
57 | + | ||
58 | + while (nsect) { | ||
59 | + if (block_count-- == 0) | ||
60 | + break; | ||
61 | + | ||
62 | + /* Get the physical block no. (bmap) */ | ||
63 | + retval = ext2fs_bmap2(fs, newino, 0, 0, 0, blk, 0, &pblk); | ||
64 | + if (retval) { | ||
65 | + fprintf(stderr, "%s: ERROR: ext2fs_bmap2() failed.\n", program); | ||
66 | + return -1; | ||
67 | + } | ||
68 | + | ||
69 | + blk++; | ||
70 | + sec = (sector_t)pblk * blksize; | ||
71 | + for (i = 0; i < blksize; i++) { | ||
72 | + *sectors++ = sec++; | ||
73 | + if (! --nsect) | ||
74 | + break; | ||
75 | + } | ||
76 | + } | ||
77 | + | ||
78 | + return 0; | ||
79 | } | ||
80 | |||
81 | static int handle_adv_on_ext(void) | ||
82 | -- | ||
83 | 1.9.1 | ||
84 | |||
diff --git a/meta/recipes-devtools/syslinux/syslinux/0008-libinstaller-syslinuxext-implement-syslinux_patch_bo.patch b/meta/recipes-devtools/syslinux/syslinux/0008-libinstaller-syslinuxext-implement-syslinux_patch_bo.patch new file mode 100644 index 0000000000..2400c98d6a --- /dev/null +++ b/meta/recipes-devtools/syslinux/syslinux/0008-libinstaller-syslinuxext-implement-syslinux_patch_bo.patch | |||
@@ -0,0 +1,427 @@ | |||
1 | From 78d76b87a4b855e6b661ae457283a63f385c04c9 Mon Sep 17 00:00:00 2001 | ||
2 | From: Robert Yang <liezhi.yang@windriver.com> | ||
3 | Date: Fri, 2 Jan 2015 12:26:46 +0800 | ||
4 | Subject: [PATCH 8/9] libinstaller/syslinuxext: implement | ||
5 | syslinux_patch_bootsect() | ||
6 | |||
7 | Move the related from extlinux/main.c to libinstaller/syslinuxext.c, the | ||
8 | syslinux_patch_bootsect() are used by both extlinux/main.c and | ||
9 | linux/syslinux.c. | ||
10 | |||
11 | Upstream-Status: Submitted | ||
12 | |||
13 | Signed-off-by: Robert Yang <liezhi.yang@windriver.com> | ||
14 | Tested-by: Du Dolpher <dolpher.du@intel.com> | ||
15 | --- | ||
16 | extlinux/Makefile | 3 +- | ||
17 | extlinux/main.c | 167 +------------------------------------------- | ||
18 | libinstaller/syslinuxext.c | 170 +++++++++++++++++++++++++++++++++++++++++++++ | ||
19 | 3 files changed, 175 insertions(+), 165 deletions(-) | ||
20 | |||
21 | diff --git a/extlinux/Makefile b/extlinux/Makefile | ||
22 | index 02d1db5..90dd92f 100644 | ||
23 | --- a/extlinux/Makefile | ||
24 | +++ b/extlinux/Makefile | ||
25 | @@ -31,7 +31,8 @@ SRCS = main.c \ | ||
26 | ../libinstaller/advio.c \ | ||
27 | ../libinstaller/bootsect_bin.c \ | ||
28 | ../libinstaller/ldlinuxc32_bin.c \ | ||
29 | - ../libinstaller/ldlinux_bin.c | ||
30 | + ../libinstaller/ldlinux_bin.c \ | ||
31 | + ../libinstaller/syslinuxext.c | ||
32 | OBJS = $(patsubst %.c,%.o,$(notdir $(SRCS))) | ||
33 | |||
34 | .SUFFIXES: .c .o .i .s .S | ||
35 | diff --git a/extlinux/main.c b/extlinux/main.c | ||
36 | index 09740bd..6fe026e 100644 | ||
37 | --- a/extlinux/main.c | ||
38 | +++ b/extlinux/main.c | ||
39 | @@ -60,6 +60,7 @@ | ||
40 | #include "setadv.h" | ||
41 | #include "syslxopt.h" /* unified options */ | ||
42 | #include "mountinfo.h" | ||
43 | +#include "syslinuxext.h" | ||
44 | |||
45 | #ifdef DEBUG | ||
46 | # define dprintf printf | ||
47 | @@ -67,10 +68,6 @@ | ||
48 | # define dprintf(...) ((void)0) | ||
49 | #endif | ||
50 | |||
51 | -#ifndef EXT2_SUPER_OFFSET | ||
52 | -#define EXT2_SUPER_OFFSET 1024 | ||
53 | -#endif | ||
54 | - | ||
55 | /* Since we have unused 2048 bytes in the primary AG of an XFS partition, | ||
56 | * we will use the first 0~512 bytes starting from 2048 for the Syslinux | ||
57 | * boot sector. | ||
58 | @@ -92,136 +89,6 @@ static char subvol[BTRFS_SUBVOL_MAX]; | ||
59 | - 2*ADV_SIZE) | ||
60 | |||
61 | /* | ||
62 | - * Get the size of a block device | ||
63 | - */ | ||
64 | -static uint64_t get_size(int devfd) | ||
65 | -{ | ||
66 | - uint64_t bytes; | ||
67 | - uint32_t sects; | ||
68 | - struct stat st; | ||
69 | - | ||
70 | -#ifdef BLKGETSIZE64 | ||
71 | - if (!ioctl(devfd, BLKGETSIZE64, &bytes)) | ||
72 | - return bytes; | ||
73 | -#endif | ||
74 | - if (!ioctl(devfd, BLKGETSIZE, §s)) | ||
75 | - return (uint64_t) sects << 9; | ||
76 | - else if (!fstat(devfd, &st) && st.st_size) | ||
77 | - return st.st_size; | ||
78 | - else | ||
79 | - return 0; | ||
80 | -} | ||
81 | - | ||
82 | -/* | ||
83 | - * Get device geometry and partition offset | ||
84 | - */ | ||
85 | -struct geometry_table { | ||
86 | - uint64_t bytes; | ||
87 | - struct hd_geometry g; | ||
88 | -}; | ||
89 | - | ||
90 | -static int sysfs_get_offset(int devfd, unsigned long *start) | ||
91 | -{ | ||
92 | - struct stat st; | ||
93 | - char sysfs_name[128]; | ||
94 | - FILE *f; | ||
95 | - int rv; | ||
96 | - | ||
97 | - if (fstat(devfd, &st)) | ||
98 | - return -1; | ||
99 | - | ||
100 | - if ((size_t)snprintf(sysfs_name, sizeof sysfs_name, | ||
101 | - "/sys/dev/block/%u:%u/start", | ||
102 | - major(st.st_rdev), minor(st.st_rdev)) | ||
103 | - >= sizeof sysfs_name) | ||
104 | - return -1; | ||
105 | - | ||
106 | - f = fopen(sysfs_name, "r"); | ||
107 | - if (!f) | ||
108 | - return -1; | ||
109 | - | ||
110 | - rv = fscanf(f, "%lu", start); | ||
111 | - fclose(f); | ||
112 | - | ||
113 | - return (rv == 1) ? 0 : -1; | ||
114 | -} | ||
115 | - | ||
116 | -/* Standard floppy disk geometries, plus LS-120. Zipdisk geometry | ||
117 | - (x/64/32) is the final fallback. I don't know what LS-240 has | ||
118 | - as its geometry, since I don't have one and don't know anyone that does, | ||
119 | - and Google wasn't helpful... */ | ||
120 | -static const struct geometry_table standard_geometries[] = { | ||
121 | - {360 * 1024, {2, 9, 40, 0}}, | ||
122 | - {720 * 1024, {2, 9, 80, 0}}, | ||
123 | - {1200 * 1024, {2, 15, 80, 0}}, | ||
124 | - {1440 * 1024, {2, 18, 80, 0}}, | ||
125 | - {1680 * 1024, {2, 21, 80, 0}}, | ||
126 | - {1722 * 1024, {2, 21, 80, 0}}, | ||
127 | - {2880 * 1024, {2, 36, 80, 0}}, | ||
128 | - {3840 * 1024, {2, 48, 80, 0}}, | ||
129 | - {123264 * 1024, {8, 32, 963, 0}}, /* LS120 */ | ||
130 | - {0, {0, 0, 0, 0}} | ||
131 | -}; | ||
132 | - | ||
133 | -int get_geometry(int devfd, uint64_t totalbytes, struct hd_geometry *geo) | ||
134 | -{ | ||
135 | - struct floppy_struct fd_str; | ||
136 | - struct loop_info li; | ||
137 | - struct loop_info64 li64; | ||
138 | - const struct geometry_table *gp; | ||
139 | - int rv = 0; | ||
140 | - | ||
141 | - memset(geo, 0, sizeof *geo); | ||
142 | - | ||
143 | - if (!ioctl(devfd, HDIO_GETGEO, geo)) { | ||
144 | - goto ok; | ||
145 | - } else if (!ioctl(devfd, FDGETPRM, &fd_str)) { | ||
146 | - geo->heads = fd_str.head; | ||
147 | - geo->sectors = fd_str.sect; | ||
148 | - geo->cylinders = fd_str.track; | ||
149 | - geo->start = 0; | ||
150 | - goto ok; | ||
151 | - } | ||
152 | - | ||
153 | - /* Didn't work. Let's see if this is one of the standard geometries */ | ||
154 | - for (gp = standard_geometries; gp->bytes; gp++) { | ||
155 | - if (gp->bytes == totalbytes) { | ||
156 | - memcpy(geo, &gp->g, sizeof *geo); | ||
157 | - goto ok; | ||
158 | - } | ||
159 | - } | ||
160 | - | ||
161 | - /* Didn't work either... assign a geometry of 64 heads, 32 sectors; this is | ||
162 | - what zipdisks use, so this would help if someone has a USB key that | ||
163 | - they're booting in USB-ZIP mode. */ | ||
164 | - | ||
165 | - geo->heads = opt.heads ? : 64; | ||
166 | - geo->sectors = opt.sectors ? : 32; | ||
167 | - geo->cylinders = totalbytes / (geo->heads * geo->sectors << SECTOR_SHIFT); | ||
168 | - geo->start = 0; | ||
169 | - | ||
170 | - if (!opt.sectors && !opt.heads) { | ||
171 | - fprintf(stderr, | ||
172 | - "Warning: unable to obtain device geometry (defaulting to %d heads, %d sectors)\n" | ||
173 | - " (on hard disks, this is usually harmless.)\n", | ||
174 | - geo->heads, geo->sectors); | ||
175 | - rv = 1; /* Suboptimal result */ | ||
176 | - } | ||
177 | - | ||
178 | -ok: | ||
179 | - /* If this is a loopback device, try to set the start */ | ||
180 | - if (!ioctl(devfd, LOOP_GET_STATUS64, &li64)) | ||
181 | - geo->start = li64.lo_offset >> SECTOR_SHIFT; | ||
182 | - else if (!ioctl(devfd, LOOP_GET_STATUS, &li)) | ||
183 | - geo->start = (unsigned int)li.lo_offset >> SECTOR_SHIFT; | ||
184 | - else if (!sysfs_get_offset(devfd, &geo->start)) { | ||
185 | - /* OK */ | ||
186 | - } | ||
187 | - | ||
188 | - return rv; | ||
189 | -} | ||
190 | - | ||
191 | -/* | ||
192 | * Query the device geometry and put it into the boot sector. | ||
193 | * Map the file and put the map in the boot sector and file. | ||
194 | * Stick the "current directory" inode number into the file. | ||
195 | @@ -231,11 +98,8 @@ ok: | ||
196 | static int patch_file_and_bootblock(int fd, const char *dir, int devfd) | ||
197 | { | ||
198 | struct stat dirst, xdst; | ||
199 | - struct hd_geometry geo; | ||
200 | sector_t *sectp; | ||
201 | - uint64_t totalbytes, totalsectors; | ||
202 | int nsect; | ||
203 | - struct fat_boot_sector *sbs; | ||
204 | char *dirpath, *subpath, *xdirpath; | ||
205 | int rv; | ||
206 | |||
207 | @@ -279,33 +143,8 @@ static int patch_file_and_bootblock(int fd, const char *dir, int devfd) | ||
208 | /* Now subpath should contain the path relative to the fs base */ | ||
209 | dprintf("subpath = %s\n", subpath); | ||
210 | |||
211 | - totalbytes = get_size(devfd); | ||
212 | - get_geometry(devfd, totalbytes, &geo); | ||
213 | - | ||
214 | - if (opt.heads) | ||
215 | - geo.heads = opt.heads; | ||
216 | - if (opt.sectors) | ||
217 | - geo.sectors = opt.sectors; | ||
218 | - | ||
219 | - /* Patch this into a fake FAT superblock. This isn't because | ||
220 | - FAT is a good format in any way, it's because it lets the | ||
221 | - early bootstrap share code with the FAT version. */ | ||
222 | - dprintf("heads = %u, sect = %u\n", geo.heads, geo.sectors); | ||
223 | - | ||
224 | - sbs = (struct fat_boot_sector *)syslinux_bootsect; | ||
225 | - | ||
226 | - totalsectors = totalbytes >> SECTOR_SHIFT; | ||
227 | - if (totalsectors >= 65536) { | ||
228 | - set_16(&sbs->bsSectors, 0); | ||
229 | - } else { | ||
230 | - set_16(&sbs->bsSectors, totalsectors); | ||
231 | - } | ||
232 | - set_32(&sbs->bsHugeSectors, totalsectors); | ||
233 | - | ||
234 | - set_16(&sbs->bsBytesPerSec, SECTOR_SIZE); | ||
235 | - set_16(&sbs->bsSecPerTrack, geo.sectors); | ||
236 | - set_16(&sbs->bsHeads, geo.heads); | ||
237 | - set_32(&sbs->bsHiddenSecs, geo.start); | ||
238 | + /* Patch syslinux_bootsect */ | ||
239 | + syslinux_patch_bootsect(devfd); | ||
240 | |||
241 | /* Construct the boot file map */ | ||
242 | |||
243 | diff --git a/libinstaller/syslinuxext.c b/libinstaller/syslinuxext.c | ||
244 | index bb54cef..5a4423b 100644 | ||
245 | --- a/libinstaller/syslinuxext.c | ||
246 | +++ b/libinstaller/syslinuxext.c | ||
247 | @@ -1,7 +1,177 @@ | ||
248 | #define _GNU_SOURCE | ||
249 | |||
250 | +#include <sys/stat.h> | ||
251 | +#include <sys/types.h> | ||
252 | +#include <getopt.h> | ||
253 | +#include <ext2fs/ext2fs.h> | ||
254 | + | ||
255 | +#include "linuxioctl.h" | ||
256 | +#include "syslinux.h" | ||
257 | +#include "syslxint.h" | ||
258 | +#include "syslxopt.h" | ||
259 | + | ||
260 | +/* | ||
261 | + * Get the size of a block device | ||
262 | + */ | ||
263 | +static uint64_t get_size(int dev_fd) | ||
264 | +{ | ||
265 | + uint64_t bytes; | ||
266 | + uint32_t sects; | ||
267 | + struct stat st; | ||
268 | + | ||
269 | +#ifdef BLKGETSIZE64 | ||
270 | + if (!ioctl(dev_fd, BLKGETSIZE64, &bytes)) | ||
271 | + return bytes; | ||
272 | +#endif | ||
273 | + if (!ioctl(dev_fd, BLKGETSIZE, §s)) | ||
274 | + return (uint64_t) sects << 9; | ||
275 | + else if (!fstat(dev_fd, &st) && st.st_size) | ||
276 | + return st.st_size; | ||
277 | + else | ||
278 | + return 0; | ||
279 | +} | ||
280 | + | ||
281 | +/* | ||
282 | + * Get device geometry and partition offset | ||
283 | + */ | ||
284 | +static struct geometry_table { | ||
285 | + uint64_t bytes; | ||
286 | + struct hd_geometry g; | ||
287 | +}; | ||
288 | + | ||
289 | +static int sysfs_get_offset(int dev_fd, unsigned long *start) | ||
290 | +{ | ||
291 | + struct stat st; | ||
292 | + char sysfs_name[128]; | ||
293 | + FILE *f; | ||
294 | + int rv; | ||
295 | + | ||
296 | + if (fstat(dev_fd, &st)) | ||
297 | + return -1; | ||
298 | + | ||
299 | + if ((size_t)snprintf(sysfs_name, sizeof sysfs_name, | ||
300 | + "/sys/dev/block/%u:%u/start", | ||
301 | + major(st.st_rdev), minor(st.st_rdev)) | ||
302 | + >= sizeof sysfs_name) | ||
303 | + return -1; | ||
304 | + | ||
305 | + f = fopen(sysfs_name, "r"); | ||
306 | + if (!f) | ||
307 | + return -1; | ||
308 | + | ||
309 | + rv = fscanf(f, "%lu", start); | ||
310 | + fclose(f); | ||
311 | + | ||
312 | + return (rv == 1) ? 0 : -1; | ||
313 | +} | ||
314 | + | ||
315 | +/* Standard floppy disk geometries, plus LS-120. Zipdisk geometry | ||
316 | + (x/64/32) is the final fallback. I don't know what LS-240 has | ||
317 | + as its geometry, since I don't have one and don't know anyone that does, | ||
318 | + and Google wasn't helpful... */ | ||
319 | +static const struct geometry_table standard_geometries[] = { | ||
320 | + {360 * 1024, {2, 9, 40, 0}}, | ||
321 | + {720 * 1024, {2, 9, 80, 0}}, | ||
322 | + {1200 * 1024, {2, 15, 80, 0}}, | ||
323 | + {1440 * 1024, {2, 18, 80, 0}}, | ||
324 | + {1680 * 1024, {2, 21, 80, 0}}, | ||
325 | + {1722 * 1024, {2, 21, 80, 0}}, | ||
326 | + {2880 * 1024, {2, 36, 80, 0}}, | ||
327 | + {3840 * 1024, {2, 48, 80, 0}}, | ||
328 | + {123264 * 1024, {8, 32, 963, 0}}, /* LS120 */ | ||
329 | + {0, {0, 0, 0, 0}} | ||
330 | +}; | ||
331 | + | ||
332 | +static int get_geometry(int dev_fd, uint64_t totalbytes, struct hd_geometry *geo) | ||
333 | +{ | ||
334 | + struct floppy_struct fd_str; | ||
335 | + struct loop_info li; | ||
336 | + struct loop_info64 li64; | ||
337 | + const struct geometry_table *gp; | ||
338 | + int rv = 0; | ||
339 | + | ||
340 | + memset(geo, 0, sizeof *geo); | ||
341 | + | ||
342 | + if (!ioctl(dev_fd, HDIO_GETGEO, geo)) { | ||
343 | + goto ok; | ||
344 | + } else if (!ioctl(dev_fd, FDGETPRM, &fd_str)) { | ||
345 | + geo->heads = fd_str.head; | ||
346 | + geo->sectors = fd_str.sect; | ||
347 | + geo->cylinders = fd_str.track; | ||
348 | + geo->start = 0; | ||
349 | + goto ok; | ||
350 | + } | ||
351 | + | ||
352 | + /* Didn't work. Let's see if this is one of the standard geometries */ | ||
353 | + for (gp = standard_geometries; gp->bytes; gp++) { | ||
354 | + if (gp->bytes == totalbytes) { | ||
355 | + memcpy(geo, &gp->g, sizeof *geo); | ||
356 | + goto ok; | ||
357 | + } | ||
358 | + } | ||
359 | + | ||
360 | + /* Didn't work either... assign a geometry of 64 heads, 32 sectors; this is | ||
361 | + what zipdisks use, so this would help if someone has a USB key that | ||
362 | + they're booting in USB-ZIP mode. */ | ||
363 | + | ||
364 | + geo->heads = opt.heads ? : 64; | ||
365 | + geo->sectors = opt.sectors ? : 32; | ||
366 | + geo->cylinders = totalbytes / (geo->heads * geo->sectors << SECTOR_SHIFT); | ||
367 | + geo->start = 0; | ||
368 | + | ||
369 | + if (!opt.sectors && !opt.heads) { | ||
370 | + fprintf(stderr, | ||
371 | + "Warning: unable to obtain device geometry (defaulting to %d heads, %d sectors)\n" | ||
372 | + " (on hard disks, this is usually harmless.)\n", | ||
373 | + geo->heads, geo->sectors); | ||
374 | + rv = 1; /* Suboptimal result */ | ||
375 | + } | ||
376 | + | ||
377 | +ok: | ||
378 | + /* If this is a loopback device, try to set the start */ | ||
379 | + if (!ioctl(dev_fd, LOOP_GET_STATUS64, &li64)) | ||
380 | + geo->start = li64.lo_offset >> SECTOR_SHIFT; | ||
381 | + else if (!ioctl(dev_fd, LOOP_GET_STATUS, &li)) | ||
382 | + geo->start = (unsigned int)li.lo_offset >> SECTOR_SHIFT; | ||
383 | + else if (!sysfs_get_offset(dev_fd, &geo->start)) { | ||
384 | + /* OK */ | ||
385 | + } | ||
386 | + | ||
387 | + return rv; | ||
388 | +} | ||
389 | + | ||
390 | + | ||
391 | /* Patch syslinux_bootsect */ | ||
392 | void syslinux_patch_bootsect(int dev_fd) | ||
393 | { | ||
394 | + uint64_t totalbytes, totalsectors; | ||
395 | + struct hd_geometry geo; | ||
396 | + struct fat_boot_sector *sbs; | ||
397 | + | ||
398 | + totalbytes = get_size(dev_fd); | ||
399 | + get_geometry(dev_fd, totalbytes, &geo); | ||
400 | + | ||
401 | + if (opt.heads) | ||
402 | + geo.heads = opt.heads; | ||
403 | + if (opt.sectors) | ||
404 | + geo.sectors = opt.sectors; | ||
405 | + | ||
406 | + /* Patch this into a fake FAT superblock. This isn't because | ||
407 | + FAT is a good format in any way, it's because it lets the | ||
408 | + early bootstrap share code with the FAT version. */ | ||
409 | + sbs = (struct fat_boot_sector *)syslinux_bootsect; | ||
410 | + | ||
411 | + totalsectors = totalbytes >> SECTOR_SHIFT; | ||
412 | + if (totalsectors >= 65536) { | ||
413 | + set_16(&sbs->bsSectors, 0); | ||
414 | + } else { | ||
415 | + set_16(&sbs->bsSectors, totalsectors); | ||
416 | + } | ||
417 | + set_32(&sbs->bsHugeSectors, totalsectors); | ||
418 | + | ||
419 | + set_16(&sbs->bsBytesPerSec, SECTOR_SIZE); | ||
420 | + set_16(&sbs->bsSecPerTrack, geo.sectors); | ||
421 | + set_16(&sbs->bsHeads, geo.heads); | ||
422 | + set_32(&sbs->bsHiddenSecs, geo.start); | ||
423 | } | ||
424 | |||
425 | -- | ||
426 | 1.9.1 | ||
427 | |||
diff --git a/meta/recipes-devtools/syslinux/syslinux/0009-linux-syslinux-implement-install_bootblock.patch b/meta/recipes-devtools/syslinux/syslinux/0009-linux-syslinux-implement-install_bootblock.patch new file mode 100644 index 0000000000..cd89d92485 --- /dev/null +++ b/meta/recipes-devtools/syslinux/syslinux/0009-linux-syslinux-implement-install_bootblock.patch | |||
@@ -0,0 +1,50 @@ | |||
1 | From 76c465e87312dbc6cffd05427f1f4d2ebdee4f13 Mon Sep 17 00:00:00 2001 | ||
2 | From: Robert Yang <liezhi.yang@windriver.com> | ||
3 | Date: Fri, 2 Jan 2015 12:28:35 +0800 | ||
4 | Subject: [PATCH 9/9] linux/syslinux: implement install_bootblock() | ||
5 | |||
6 | Refer to the install_bootblock() in extlinux/main.c to make | ||
7 | linux/syslinux.c's install_bootblock() which only supports ext2/3/4. | ||
8 | |||
9 | Upstream-Status: Submitted | ||
10 | |||
11 | Signed-off-by: Robert Yang <liezhi.yang@windriver.com> | ||
12 | Tested-by: Du Dolpher <dolpher.du@intel.com> | ||
13 | --- | ||
14 | linux/syslinux.c | 20 ++++++++++++++++++++ | ||
15 | 1 file changed, 20 insertions(+) | ||
16 | |||
17 | diff --git a/linux/syslinux.c b/linux/syslinux.c | ||
18 | index c741750..917f83a 100755 | ||
19 | --- a/linux/syslinux.c | ||
20 | +++ b/linux/syslinux.c | ||
21 | @@ -419,6 +419,26 @@ static int ext_file_write(ext2_file_t e2_file, const void *buf, size_t count, | ||
22 | */ | ||
23 | int install_bootblock(int fd, const char *device) | ||
24 | { | ||
25 | + struct ext2_super_block sb; | ||
26 | + | ||
27 | + if (xpread(fd, &sb, sizeof sb, EXT2_SUPER_OFFSET + opt.offset) != sizeof sb) { | ||
28 | + perror("reading superblock"); | ||
29 | + return 1; | ||
30 | + } | ||
31 | + | ||
32 | + if (sb.s_magic != EXT2_SUPER_MAGIC) { | ||
33 | + fprintf(stderr, | ||
34 | + "no ext2/3/4 superblock found on %s\n", device); | ||
35 | + return 1; | ||
36 | + } | ||
37 | + | ||
38 | + if (xpwrite(fd, syslinux_bootsect, syslinux_bootsect_len, 0) | ||
39 | + != (signed)syslinux_bootsect_len) { | ||
40 | + perror("writing bootblock"); | ||
41 | + return 1; | ||
42 | + } | ||
43 | + | ||
44 | + return 0; | ||
45 | } | ||
46 | |||
47 | /* The file's block count */ | ||
48 | -- | ||
49 | 1.9.1 | ||
50 | |||
diff --git a/meta/recipes-devtools/syslinux/syslinux_6.03.bb b/meta/recipes-devtools/syslinux/syslinux_6.03.bb index 7e3176e84e..33dd776f1b 100644 --- a/meta/recipes-devtools/syslinux/syslinux_6.03.bb +++ b/meta/recipes-devtools/syslinux/syslinux_6.03.bb | |||
@@ -6,12 +6,21 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=0636e73ff0215e8d672dc4c32c317bb3 \ | |||
6 | 6 | ||
7 | # If you really want to run syslinux, you need mtools. We just want the | 7 | # If you really want to run syslinux, you need mtools. We just want the |
8 | # ldlinux.* stuff for now, so skip mtools-native | 8 | # ldlinux.* stuff for now, so skip mtools-native |
9 | DEPENDS = "nasm-native util-linux" | 9 | DEPENDS = "nasm-native util-linux e2fsprogs" |
10 | 10 | ||
11 | SRC_URI = "${KERNELORG_MIRROR}/linux/utils/boot/syslinux/6.xx/syslinux-${PV}.tar.xz \ | 11 | SRC_URI = "${KERNELORG_MIRROR}/linux/utils/boot/syslinux/6.xx/syslinux-${PV}.tar.xz \ |
12 | file://syslinux-fix-parallel-building-issue.patch \ | 12 | file://syslinux-fix-parallel-building-issue.patch \ |
13 | file://syslinux-libupload-depend-lib.patch \ | 13 | file://syslinux-libupload-depend-lib.patch \ |
14 | file://syslinux-remove-clean-script.patch \ | 14 | file://syslinux-remove-clean-script.patch \ |
15 | file://0001-linux-syslinux-support-ext2-3-4-device.patch \ | ||
16 | file://0002-linux-syslinux-implement-open_ext2_fs.patch \ | ||
17 | file://0003-linux-syslinux-implement-install_to_ext2.patch \ | ||
18 | file://0004-linux-syslinux-add-ext_file_read-and-ext_file_write.patch \ | ||
19 | file://0005-linux-syslinux-implement-handle_adv_on_ext.patch \ | ||
20 | file://0006-linux-syslinux-implement-write_to_ext-and-add-syslin.patch \ | ||
21 | file://0007-linux-syslinux-implement-ext_construct_sectmap_fs.patch \ | ||
22 | file://0008-libinstaller-syslinuxext-implement-syslinux_patch_bo.patch \ | ||
23 | file://0009-linux-syslinux-implement-install_bootblock.patch \ | ||
15 | " | 24 | " |
16 | 25 | ||
17 | SRC_URI[md5sum] = "92a253df9211e9c20172796ecf388f13" | 26 | SRC_URI[md5sum] = "92a253df9211e9c20172796ecf388f13" |